Quite a bit of work done on news-items, and it all compiles.
I was actually trying to work on genetic buildings, but...
This commit is contained in:
parent
9e8d59c2d1
commit
5c70bd0c91
File diff suppressed because one or more lines are too long
35
docs/codox/Canonical-dictionary.html
Normal file
35
docs/codox/Canonical-dictionary.html
Normal file
File diff suppressed because one or more lines are too long
41
docs/codox/Dynamic-consequences.html
Normal file
41
docs/codox/Dynamic-consequences.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
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
22
docs/codox/Roadmap.html
Normal file
22
docs/codox/Roadmap.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
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
7
docs/codox/building_on_microworld.html
Normal file
7
docs/codox/building_on_microworld.html
Normal file
File diff suppressed because one or more lines are too long
10
docs/codox/cc.journeyman.the-great-game.agent.agent.html
Normal file
10
docs/codox/cc.journeyman.the-great-game.agent.agent.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
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
3
docs/codox/cc.journeyman.the-great-game.playroom.html
Normal file
3
docs/codox/cc.journeyman.the-great-game.playroom.html
Normal file
File diff suppressed because one or more lines are too long
3
docs/codox/cc.journeyman.the-great-game.time.html
Normal file
3
docs/codox/cc.journeyman.the-great-game.time.html
Normal file
File diff suppressed because one or more lines are too long
3
docs/codox/cc.journeyman.the-great-game.utils.html
Normal file
3
docs/codox/cc.journeyman.the-great-game.utils.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
docs/codox/cc.journeyman.the-great-game.world.mw.html
Normal file
3
docs/codox/cc.journeyman.the-great-game.world.mw.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
3
docs/codox/cc.journeyman.the-great-game.world.run.html
Normal file
3
docs/codox/cc.journeyman.the-great-game.world.run.html
Normal file
File diff suppressed because one or more lines are too long
3
docs/codox/cc.journeyman.the-great-game.world.world.html
Normal file
3
docs/codox/cc.journeyman.the-great-game.world.world.html
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
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
81
src/cc/journeyman/the_great_game/buildings/module.clj
Normal file
81
src/cc/journeyman/the_great_game/buildings/module.clj
Normal file
|
@ -0,0 +1,81 @@
|
|||
(ns cc.journeyman.the-great-game.buildings.module
|
||||
|
||||
"A module of a building; essentially something like a portacabin, which can be
|
||||
assembled together with other modules to make a complete building.
|
||||
|
||||
Modules need to include
|
||||
|
||||
1. Ground floor modules, having external doors;
|
||||
2. Craft modules -- workshops -- which will normally be ground floor (except
|
||||
weavers) and may have the constraint that no upper floor module can cover them;
|
||||
3. Upper floor modules, having NO external doors (but linking internal doors);
|
||||
4. Roof modules
|
||||
|
||||
**Role** must be one of:
|
||||
|
||||
1. `:primary` a ground floor main entrance module
|
||||
2. `:secondary` a module which can be upper or ground floor
|
||||
3. `:upper` a module which can only be on an upper floor, for example one
|
||||
with a projecting gallery, balcony or overhang.
|
||||
|
||||
Other values for `role` will emerge.
|
||||
|
||||
**Exits** must be a sequence of keywords taken from the following list:
|
||||
|
||||
1. `:left` an exit in the centre of the left wall
|
||||
2. `:left-front` an exit in the centre of the left half of the front wall
|
||||
3. `:front` an exit in the centre of the front wall
|
||||
4. `:right-front` an exit in the centre of the right half of the front wall
|
||||
5. `:right` an exit in the centre of the right wall
|
||||
6. `:right-back` an exit in the centre of the right half of the back wall
|
||||
7. `:left-back` an exit in the centre of the back wall
|
||||
|
||||
A module placed on an upper floor must have no exit which opens beyond the
|
||||
footprint of the floor below - no doors into mid air! However, it is allowable
|
||||
(and indeed is necessary) to allow doors into roof spaces if the adjacent
|
||||
module on the same floor does not yet exist, since otherwise it would be
|
||||
impossible to access a new room which might later be built there.
|
||||
|
||||
**Load** must be a small integer indicating both the weight of the module and
|
||||
the total amount of weight it can support. So for example a stone-built module
|
||||
might have a `load` value of 4, a brick built one of 3, and a half-timbered one
|
||||
of 2, and a tent of 0. This means a stone ground floor module could support one
|
||||
further floor of stone or brick, or two further floors of half timbered
|
||||
construction; while a brick built ground floor could support a single brick or
|
||||
half-timbered upper floor but not a stone one, and a half-timbered ground floor
|
||||
could only support a half timbered upper floor.
|
||||
|
||||
There also needs to be an undercroft or platform module, such that the area of
|
||||
the top of the platform is identical with the footprint of the building, and
|
||||
the altitude of the top of the platform is equal to the altitude of the
|
||||
terrain at the heighest corner of the building; so that the actual
|
||||
building doesn't float in the air, and also so that none of the doors or windows
|
||||
are partly underground.
|
||||
|
||||
Each module needs to wrap an actual 3d model created in Blender or whatever,
|
||||
and have a list of optional **textures** with which that model can be rendered.
|
||||
So an upper floor bedroom module might have the following renders:
|
||||
|
||||
1. Bare masonry - constrained to upland or plateau terrain, and to coastal culture
|
||||
2. Painted masonry - constrained to upland or plateau terrain, and to coastal culture
|
||||
3. Half-timbered - not available on plateau terrain
|
||||
4. Weatherboarded - constrained to forest terrain
|
||||
5. Brick - constrained to arable or arid terrain
|
||||
|
||||
of course these are only examples, and also, it's entirely possible to have
|
||||
for example multiple different weatherboard renders for the same module.
|
||||
There needs to be a way of rendering what can be built above what: for
|
||||
example, you can't have a masonry clad module over a half timbered one,
|
||||
but you can have a half-timbered one over a masonry one.")
|
||||
|
||||
(defrecord BuildingModule
|
||||
[model
|
||||
^Double length
|
||||
^Double width
|
||||
^Double height
|
||||
^Integer load
|
||||
^clojure.lang.Keyword role
|
||||
^clojure.lang.IPersistentCollection textures
|
||||
^clojure.lang.IPersistentCollection exits
|
||||
]
|
||||
)
|
|
@ -1,83 +1,85 @@
|
|||
(ns cc.journeyman.the-great-game.buildings.rectangular
|
||||
(:require [cc.journeyman.the-great-game.holdings.holding :refer [ProtoHolding]]
|
||||
[cc.journeyman.the-great-game.location.location :refer [ProtoLocation]]
|
||||
)
|
||||
(:import [org.apache.commons.math3.random MersenneTwister]
|
||||
))
|
||||
"Build buildings with a generally rectangular floow plan.
|
||||
|
||||
## Motivations
|
||||
|
||||
Right, the idea behind this namespace is many fold.
|
||||
|
||||
1. To establish the broad principle of genetic buildings, by creating a
|
||||
function which reproducibly creates reproducible buildings at specified
|
||||
locations, such that different buildings are credibly varied but a
|
||||
building at a specified location is always (modulo economic change) the
|
||||
same.
|
||||
2. Create good rectangular buildings, and investigate whether a single
|
||||
function can be used to create buildings of more than one family (e.g.
|
||||
can it produce flat roofed, north African style, mud brick houses as
|
||||
well as pitch roofed, half timbered northern European houses?)
|
||||
3. Establish whether, in my current state of fairly severe mental illness,
|
||||
I can actually produce any usable code at all.
|
||||
|
||||
## Key factors in the creation of a building
|
||||
|
||||
### Holding
|
||||
|
||||
Every building is on a holding, and, indeed, what I mean by 'building' here
|
||||
may well turn out to be 'the collection of all the permanent structures on
|
||||
a holding. A holding is a polygonal area of the map which does not
|
||||
intersect with any other holding, but for the time being we'll make the
|
||||
simplifying assumption that every holding is a rectangular strip, and that
|
||||
'urban' holdings are of a reasonably standard width (see Viking-period
|
||||
York) and length. Rural holdings (farms, ?wood lots) may be much larger.
|
||||
|
||||
### Terrain
|
||||
|
||||
A building is made of the stuff of the place. In a forest, buildings will
|
||||
tend to be wooden; in a terrain with rocky outcrops -- normally found on
|
||||
steep slopes -- stone. On the flat lands where there's river mud, of brick,
|
||||
cob, or wattle and daub. So to build a building we need to know the
|
||||
terrain. Terrain can be inferred from location but in practice this will
|
||||
be computationally expensive, so we'll pass terrain in as an argument to
|
||||
the build function.
|
||||
|
||||
For the time being we'll pass it in simply as a keyword from a defined set
|
||||
of keywords; later it may be a more sophisticated data structure.
|
||||
|
||||
### Culture
|
||||
|
||||
People of different cultures build distinctively different buildings, even
|
||||
when using the same materials. So, in our world, a Japanese wooden house
|
||||
looks quite different from an Anglo Saxon stave house which looks quite
|
||||
different from a Canadian log cabin, even though the materials are much the
|
||||
same and the tools available to build with are not much different.
|
||||
|
||||
Culture can affect not just the overall shape of a building but also its
|
||||
finish and surface detail. For example, in many places in England, stone
|
||||
buildings are typically left bare; in rural Scotland, typically painted
|
||||
white or in pastel shades; in Ireland, often quite vivid colours.
|
||||
|
||||
People may also show religious or cultural symbols on their buildings.
|
||||
|
||||
For all these reasons, we need to know the culture of the occupant when
|
||||
creating a building. Again, this will initially be passed in as a keyword.
|
||||
|
||||
### Craft
|
||||
|
||||
People in the game world have a craft, and some crafts will require
|
||||
different features in the building. In the broadly late-bronze-age-to
|
||||
medieval period within which the game is set, residence and workplace
|
||||
are for most people pretty much the same.
|
||||
|
||||
So a baker needs an oven, a smith a forge, and so on. All crafts who do
|
||||
some degree retail trade will want a shop front as part of the ground
|
||||
floor of their dwelling. Merchants and bankers will probably have houses
|
||||
that are a bit more showy than others.
|
||||
|
||||
Whether the 'genetic buildings' idea will ever really produce suitable
|
||||
buildings for aristons I don't know; it seems more likely that significant
|
||||
strongholds (of which there will be relatively few) should all be hand
|
||||
modelled rather than procedurally generated."
|
||||
(:require [cc.journeyman.the-great-game.holdings.holding :refer [ProtoHolding]]
|
||||
[cc.journeyman.the-great-game.location.location :refer [ProtoLocation]])
|
||||
(:import [org.apache.commons.math3.random MersenneTwister]))
|
||||
|
||||
;;; Right, the idea behind this namespace is many fold.
|
||||
;;;
|
||||
;;; 1. To establish the broad principle of genetic buildings, by creating a
|
||||
;;; function which reproducibly creates reproducible buildings at specified
|
||||
;;; locations, such that different buildings are credibly varied but a
|
||||
;;; building at a specified location is always (modulo economic change) the
|
||||
;;; same.
|
||||
;;; 2. Create good rectangular buildings, and investigate whether a single
|
||||
;;; function can be used to create buildings of more than one family (e.g.
|
||||
;;; can it produce flat roofed, north African style, mud brick houses as
|
||||
;;; well as pitch roofed, half timbered northern European houses?)
|
||||
;;; 3. Establish whether, in my current state of fairly severe mental illness,
|
||||
;;; I can actually produce any usable code at all.
|
||||
;;;
|
||||
;;; ## Key factors in the creation of a building
|
||||
;;;
|
||||
;;; ### Holding
|
||||
;;;
|
||||
;;; Every building is on a holding, and, indeed, what I mean by 'building' here
|
||||
;;; may well turn out to be 'the collection of all the permanent structures on
|
||||
;;; a holding. A holding is a polygonal area of the map which does not
|
||||
;;; intersect with any other holding, but for the time being we'll make the
|
||||
;;; simplifying assumption that every holding is a rectangular strip, and that
|
||||
;;; 'urban' holdings are of a reasonably standard width (see Viking-period
|
||||
;;; York) and length. Rural holdings (farms, ?wood lots) may be much larger.
|
||||
;;;
|
||||
;;; ### Terrain
|
||||
;;;
|
||||
;;; A building is made of the stuff of the place. In a forest, buildings will
|
||||
;;; tend to be wooden; in a terrain with rocky outcrops -- normally found on
|
||||
;;; steep slopes -- stone. On the flat lands where there's river mud, of brick,
|
||||
;;; cob, or wattle and daub. So to build a building we need to know the
|
||||
;;; terrain. Terrain can be inferred from location but in practice this will
|
||||
;;; be computationally expensive, so we'll pass terrain in as an argument to
|
||||
;;; the build function.
|
||||
;;;
|
||||
;;; For the time being we'll pass it in simply as a keyword from a defined set
|
||||
;;; of keywords; later it may be a more sophisticated data structure.
|
||||
;;;
|
||||
;;; ### Culture
|
||||
;;;
|
||||
;;; People of different cultures build distinctively different buildings, even
|
||||
;;; when using the same materials. So, in our world, a Japanese wooden house
|
||||
;;; looks quite different from an Anglo Saxon stave house which looks quite
|
||||
;;; different from a Canadian log cabin, even though the materials are much the
|
||||
;;; same and the tools available to build with are not much different.
|
||||
;;;
|
||||
;;; Culture can affect not just the overall shape of a building but also its
|
||||
;;; finish and surface detail. For example, in many places in England, stone
|
||||
;;; buildings are typically left bare; in rural Scotland, typically painted
|
||||
;;; white or in pastel shades; in Ireland, often quite vivid colours.
|
||||
;;;
|
||||
;;; People may also show religious or cultural symbols on their buildings.
|
||||
;;;
|
||||
;;; For all these reasons, we need to know the culture of the occupant when
|
||||
;;; creating a building. Again, this will initially be passed in as a keyword.
|
||||
;;;
|
||||
;;; ### Craft
|
||||
;;;
|
||||
;;; People in the game world have a craft, and some crafts will require
|
||||
;;; different features in the building. In the broadly late-bronze-age-to
|
||||
;;; medieval period within which the game is set, residence and workplace
|
||||
;;; are for most people pretty much the same.
|
||||
;;;
|
||||
;;; So a baker needs an oven, a smith a forge, and so on. All crafts who do
|
||||
;;; some degree retail trade will want a shop front as part of the ground
|
||||
;;; floor of their dwelling. Merchants and bankers will probably have houses
|
||||
;;; that are a bit more showy than others.
|
||||
;;;
|
||||
;;; Whether the 'genetic buildings' idea will ever really produce suitable
|
||||
;;; buildings for aristons I don't know; it seems more likely that significant
|
||||
;;; strongholds (of which there will be relatively few) should all be hand
|
||||
;;; modelled rather than procedurally generated.
|
||||
|
||||
(def ^:dynamic *terrain-types*
|
||||
"Types of terrain which affect building families. TODO: This is a placeholder;
|
||||
|
@ -94,6 +96,16 @@
|
|||
#{:baker :banker :butcher :chancellor :innkeeper :lawyer :magus :merchant :miller :priest :scholar :smith :weaver})
|
||||
|
||||
(def ^:dynamic *building-families*
|
||||
"Families of buildings.
|
||||
|
||||
Each family has
|
||||
|
||||
* terrain types to which it is appropriate;
|
||||
* crafts to which it is appropriate;
|
||||
* cultures to which it is appropriate.
|
||||
|
||||
Each generated building will be of one family, and will comprise modules
|
||||
taken only from that family."
|
||||
{:pitched-rectangular {:terrains #{:arable :forest :upland}
|
||||
:crafts *crafts*
|
||||
:cultures #{:coastal :western-clans}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
(ns cc.journeyman.the-great-game.gossip.gossip
|
||||
"Interchange of news events between gossip agents"
|
||||
(:require [cc.journeyman.the-great-game.utils :refer [deep-merge]]
|
||||
[cc.journeyman.the-great-game.gossip.news-items :refer [learn-news-item]]))
|
||||
"Interchange of news events between gossip agents.
|
||||
|
||||
Note that habitual travellers are all gossip agents; specifically, at this
|
||||
stage, that means merchants. When merchants are moved we also need to
|
||||
update the location of the gossip with the same key.
|
||||
|
||||
Innkeepers are also gossip agents but do not typically move."
|
||||
(:require [cc.journeyman.the-great-game.utils :refer [deep-merge]]
|
||||
[cc.journeyman.the-great-game.gossip.news-items :refer [learn-news-item]]
|
||||
))
|
||||
|
||||
;; Note that habitual travellers are all gossip agents; specifically, at this
|
||||
;; stage, that means merchants. When merchants are moved we also need to
|
||||
;; update the location of the gossip with the same key.
|
||||
|
||||
(defn dialogue
|
||||
"Dialogue between an `enquirer` and an `agent` in this `world`; returns a
|
||||
|
@ -16,30 +20,26 @@
|
|||
enquirer)
|
||||
|
||||
(defn gather-news
|
||||
([world]
|
||||
(reduce
|
||||
deep-merge
|
||||
world
|
||||
(map
|
||||
#(gather-news world %)
|
||||
(keys (:gossips world)))))
|
||||
([world gossip]
|
||||
(let [g (cond (keyword? gossip)
|
||||
(-> world :gossips gossip)
|
||||
(map? gossip)
|
||||
gossip)]
|
||||
{:gossips
|
||||
{(:id g)
|
||||
(reduce
|
||||
"Gather news for the specified `gossip` in this `world`."
|
||||
[world gossip]
|
||||
(let [g (cond (keyword? gossip)
|
||||
(-> world :gossips gossip)
|
||||
(map? gossip)
|
||||
gossip)]
|
||||
(if g
|
||||
{:gossips
|
||||
{(:id g)
|
||||
(reduce
|
||||
deep-merge
|
||||
{}
|
||||
(map
|
||||
#(dialogue g % world)
|
||||
(remove
|
||||
#( = g %)
|
||||
(filter
|
||||
#(= (:location %) (:location g))
|
||||
(vals (:gossips world))))))}})))
|
||||
#(dialogue g % world)
|
||||
(remove
|
||||
#(= g %)
|
||||
(filter
|
||||
#(= (:location %) (:location g))
|
||||
(vals (:gossips world))))))}}
|
||||
{})))
|
||||
|
||||
(defn move-gossip
|
||||
"Return a world like this `world` but with this `gossip` moved to this
|
||||
|
@ -63,4 +63,11 @@
|
|||
"Return a world like this `world`, with news items exchanged between gossip
|
||||
agents."
|
||||
[world]
|
||||
(gather-news world))
|
||||
(reduce
|
||||
deep-merge
|
||||
world
|
||||
(map
|
||||
#(gather-news world %)
|
||||
(keys (:gossips world)))))
|
||||
|
||||
|
||||
|
|
|
@ -1,20 +1,29 @@
|
|||
(ns cc.journeyman.the-great-game.gossip.news-items
|
||||
"Categories of news events interesting to gossip agents"
|
||||
"Categories of news events interesting to gossip agents.
|
||||
|
||||
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
|
||||
advance further in the course of writing and debugging this namespace.
|
||||
|
||||
A news item is a map with the keys:
|
||||
|
||||
* `date` - the date on which the reported event happened;
|
||||
* `nth-hand` - the number of agents the news item has passed through;
|
||||
* `verb` - what it is that happened (key into `news-topics`);
|
||||
|
||||
plus other keys taken from the `keys` value associated with the verb in
|
||||
`news-topics`.
|
||||
|
||||
## Notes:
|
||||
|
||||
*TODO*
|
||||
This namespace at present considers the `:knowledge` of a gossip to be a flat
|
||||
list of propositions, each of which must be checked every time any new
|
||||
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]]))
|
||||
|
||||
;; The ideas here are based on the essay 'The spread of knowledge in a large
|
||||
;; game world', q.v.; they've advanced a little beyond that and will doubtless
|
||||
;; advance further in the course of writing and debugging this namespace.
|
||||
|
||||
;; A news item is a map with the keys:
|
||||
;;
|
||||
;; * `date` - the date on which the reported event happened;
|
||||
;; * `nth-hand` - the number of agents the news item has passed through;
|
||||
;; * `verb` - what it is that happened (key into `news-topics`);
|
||||
;;
|
||||
;; plus other keys taken from the `keys` value associated with the verb in
|
||||
;; `news-topics`
|
||||
|
||||
(def news-topics
|
||||
"Topics of interest to gossip agents. Topics are keyed in this map by
|
||||
|
@ -30,9 +39,9 @@
|
|||
action;
|
||||
* `price` is special to buy/sell, but of significant interest to merchants.
|
||||
|
||||
#### Notes:
|
||||
## 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
|
||||
|
@ -46,7 +55,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
|
||||
|
@ -56,49 +65,48 @@
|
|||
|
||||
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.
|
||||
"
|
||||
{ ;; A significant attack is interesting whether or not it leads to deaths
|
||||
:attack {:verb :attack :keys [:actor :other :location]}
|
||||
{;; 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
|
||||
:die {:verb :die :keys [:actor :location]}
|
||||
:die {:verb :die :keys [:actor :location]}
|
||||
;; Deliberate killings are interesting.
|
||||
:kill {:verb :kill :keys [:actor :other :location]
|
||||
:inferences [{:verb :die :actor :other :other :nil}]}
|
||||
:kill {:verb :kill :keys [:actor :other :location]
|
||||
:inferences [{:verb :die :actor :other :other :nil}]}
|
||||
;; Marriages may be interesting
|
||||
:marry {:verb :marry :keys [:actor :other :location]
|
||||
:inferences [{:verb :marry :actor :other :other :actor}]}
|
||||
:marry {:verb :marry :keys [:actor :other :location]
|
||||
:inferences [{:verb :marry :actor :other :other :actor}]}
|
||||
;; The end of ongoing open conflict between to characters may be interesting
|
||||
:peace {:verb :peace :keys [:actor :other :location]
|
||||
:inferences [{:verb :peace :actor :other :other :actor}]}
|
||||
:peace {:verb :peace :keys [:actor :other :location]
|
||||
:inferences [{:verb :peace :actor :other :other :actor}]}
|
||||
;; Things related to the plot are interesting, but will require special
|
||||
;; handling. Extra keys may be required by particular plot events.
|
||||
:plot {:verb :plot :keys [:actor :other :object :location]}
|
||||
:plot {:verb :plot :keys [:actor :other :object :location]}
|
||||
;; Rapes are interesting.
|
||||
:rape {:verb :rape :keys [:actor :other :location]
|
||||
:rape {:verb :rape :keys [:actor :other :location]
|
||||
;; Should you also infer from rape that actor is male and adult?
|
||||
:inferences [{:verb :attack}
|
||||
{:verb :sex}
|
||||
{:verb :sex :actor :other :other :actor}]}
|
||||
:inferences [{:verb :attack}
|
||||
{: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 :price]}
|
||||
;; Sex can juicy gossip, although not normally if the participants are in an
|
||||
;; established sexual relationship.
|
||||
:sex {:verb :sex :keys [:actor :other :location]
|
||||
:inferences [{:verb :sex :actor :other :other :actor}]}
|
||||
;; Thefts are interesting
|
||||
:steal {:verb :steal :keys [:actor :other :object :location]}
|
||||
:sex {:verb :sex :keys [:actor :other :location]
|
||||
:inferences [{:verb :sex :actor :other :other :actor}]}
|
||||
;; Thefts are interesting.
|
||||
:steal {:verb :steal :keys [:actor :other :object :location]}
|
||||
;; The succession of rulers is interesting; of respected craftsmen,
|
||||
;; potentially also interesting.
|
||||
:succession {:verb :succession :keys [:actor :other :location :rank]}
|
||||
;; The start of ongoing open conflict between to characters may be interesting
|
||||
:war {:verb :war :keys [:actor :other :location]
|
||||
:inferences [{:verb :war :actor :other :other :actor}]}
|
||||
})
|
||||
:succession {:verb :succession :keys [:actor :other :location :rank]}
|
||||
;; The start of ongoing open conflict between two characters may be interesting.
|
||||
:war {:verb :war :keys [:actor :other :location]
|
||||
:inferences [{:verb :war :actor :other :other :actor}]}})
|
||||
|
||||
|
||||
(defn interest-in-character
|
||||
|
@ -108,9 +116,9 @@
|
|||
documented above, they probably have to be maps, to allow for degradation."
|
||||
[gossip character]
|
||||
(count
|
||||
(concat
|
||||
(filter #(= (:actor % character)) (:knowledge gossip))
|
||||
(filter #(= (:other % character)) (:knowledge gossip)))))
|
||||
(concat
|
||||
(filter #(= (:actor % character)) (:knowledge gossip))
|
||||
(filter #(= (:other % character)) (:knowledge gossip)))))
|
||||
|
||||
(defn interesting-character?
|
||||
"Boolean representation of whether this `character` is interesting to this
|
||||
|
@ -133,15 +141,15 @@
|
|||
0)
|
||||
(coll? location)
|
||||
(reduce
|
||||
+
|
||||
(map
|
||||
#(interest-in-location gossip %)
|
||||
location))
|
||||
+
|
||||
(map
|
||||
#(interest-in-location gossip %)
|
||||
location))
|
||||
:else
|
||||
(count
|
||||
(filter
|
||||
#(some (fn [x] (= x location)) (:location %))
|
||||
(cons {:location (:home gossip)} (:knowledge gossip))))))
|
||||
(filter
|
||||
#(some (fn [x] (= x location)) (:location %))
|
||||
(cons {:location (:home gossip)} (:knowledge gossip))))))
|
||||
|
||||
;; (interest-in-location {:home [{0, 0} :test-home] :knowledge []} [:test-home])
|
||||
|
||||
|
@ -160,15 +168,57 @@
|
|||
;; TODO: Not yet (really) implemented
|
||||
true)
|
||||
|
||||
(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.
|
||||
|
||||
The rationale here is that if `new-value` contains new or different
|
||||
information, it's worth learning; otherwise, not."
|
||||
[new-value known-value]
|
||||
(or
|
||||
(= new-value known-value)
|
||||
;; TODO: some handwaving here about being a slightly better descriptor --
|
||||
;; having more keys than might
|
||||
(when (and (map? new-value) (map? known-value))
|
||||
(every? true? (map #(= (new-value %) (known-value %))
|
||||
(keys new-value))))))
|
||||
|
||||
(defn compatible-item?
|
||||
"True if `new-item` is identical with, or less specific than, `known-item`.
|
||||
|
||||
If we already know 'Bad Joe killed Sweet Daisy', there's no point in
|
||||
learning that 'someone killed Sweet Daisy', but there is point in learning
|
||||
'someone killed Sweet Daisy _with poison_'."
|
||||
[new-item known-item]
|
||||
(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)))))
|
||||
|
||||
(defn known-item?
|
||||
"True if this news `item` is already known to this `gossip`.
|
||||
|
||||
This means that the `gossip` already knows an item which identifiably has
|
||||
the same _or more specific_ values for all the keys of this `item` except
|
||||
`:nth-hand`, `:confidence` and `:learned-from`."
|
||||
[gossip item]
|
||||
(reduce
|
||||
#(or %1 %2)
|
||||
(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]
|
||||
(or
|
||||
(interesting-character? gossip (:actor item))
|
||||
(interesting-character? gossip (:other item))
|
||||
(interesting-location? gossip (:location item))
|
||||
(interesting-object? gossip (:object item))
|
||||
(interesting-topic? gossip (:verb item))))
|
||||
(and (not (known-item? gossip item))
|
||||
(or
|
||||
(interesting-character? gossip (:actor item))
|
||||
(interesting-character? gossip (:other item))
|
||||
(interesting-location? gossip (:location item))
|
||||
(interesting-object? gossip (:object item))
|
||||
(interesting-topic? gossip (:verb item)))))
|
||||
|
||||
(defn infer
|
||||
"Infer a new knowledge item from this `item`, following this `rule`"
|
||||
|
@ -176,11 +226,11 @@
|
|||
(reduce merge
|
||||
item
|
||||
(cons
|
||||
{:verb (:verb rule)}
|
||||
(map (fn [k] {k (apply (k rule) (list item))})
|
||||
(remove
|
||||
#(= % :verb)
|
||||
(keys rule))))))
|
||||
{:verb (:verb rule)}
|
||||
(map (fn [k] {k (apply (k rule) (list item))})
|
||||
(remove
|
||||
#(= % :verb)
|
||||
(keys rule))))))
|
||||
|
||||
(declare learn-news-item)
|
||||
|
||||
|
@ -189,11 +239,11 @@
|
|||
`item`."
|
||||
[item]
|
||||
(set
|
||||
(reduce
|
||||
concat
|
||||
(map
|
||||
#(:knowledge (learn-news-item {} (infer item %) false))
|
||||
(:inferences (news-topics (:verb item)))))))
|
||||
(reduce
|
||||
concat
|
||||
(map
|
||||
#(:knowledge (learn-news-item {} (infer item %) false))
|
||||
(:inferences (news-topics (:verb item)))))))
|
||||
|
||||
(defn degrade-character
|
||||
"Return a character specification like this `character`, but comprising
|
||||
|
@ -207,50 +257,57 @@
|
|||
only those elements this `gossip` is interested in. If none, return
|
||||
`nil`."
|
||||
[gossip location]
|
||||
(let [l (if
|
||||
(coll? location)
|
||||
(filter
|
||||
#(when (interesting-location? gossip %) %)
|
||||
location))]
|
||||
(let [l (when
|
||||
(coll? location)
|
||||
(filter
|
||||
#(when (interesting-location? gossip %) %)
|
||||
location))]
|
||||
(when-not (empty? l) l)))
|
||||
|
||||
(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 learn-news-item
|
||||
"Return a gossip like this `gossip`, which has learned this news `item` if
|
||||
it is of interest to them."
|
||||
;; TODO: Not yet implemented
|
||||
([gossip item]
|
||||
(learn-news-item gossip item true))
|
||||
([gossip item follow-inferences?]
|
||||
(if
|
||||
(interesting-item? gossip item)
|
||||
(let
|
||||
[g (assoc
|
||||
gossip
|
||||
:knowledge
|
||||
(cons
|
||||
(assoc
|
||||
item
|
||||
:nth-hand (if
|
||||
(number? (:nth-hand item))
|
||||
(inc (:nth-hand item))
|
||||
1)
|
||||
:time-stamp (if
|
||||
(number? (:time-stamp item))
|
||||
(:time-stamp item)
|
||||
(game-time))
|
||||
:location (degrade-location gossip (:location item))
|
||||
;; TODO: ought to maybe-degrade characters we're not yet interested in
|
||||
)
|
||||
;; TODO: ought not to add knowledge items we already have, except
|
||||
;; to replace if new item is of increased specificity
|
||||
(:knowledge gossip)))]
|
||||
(interesting-item? gossip item)
|
||||
(let [item' (assoc
|
||||
item
|
||||
:nth-hand (inc-or-one (:nth-hand item))
|
||||
:time-stamp (if
|
||||
(number? (:time-stamp item))
|
||||
(:time-stamp item)
|
||||
(game-time))
|
||||
:location (degrade-location gossip (:location item))
|
||||
:actor (degrade-character gossip (:actor item))
|
||||
:other (degrade-character gossip (:other item))
|
||||
;; 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
|
||||
)
|
||||
g (assoc
|
||||
gossip
|
||||
:knowledge
|
||||
(cons
|
||||
item'
|
||||
(:knowledge gossip)))]
|
||||
(if follow-inferences?
|
||||
(assoc
|
||||
g
|
||||
:knowledge
|
||||
(concat (:knowledge g) (make-all-inferences item)))
|
||||
g))
|
||||
gossip)))
|
||||
g
|
||||
:knowledge
|
||||
(concat (:knowledge g) (make-all-inferences item)))
|
||||
g)))
|
||||
gossip))
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -29,14 +29,18 @@
|
|||
;; is needed to ensure this!
|
||||
ProtoContainer
|
||||
ProtoHolding
|
||||
(frontage [holding]
|
||||
;; TODO: this is WRONG, but will work for now. The frontage should
|
||||
;; be the side of the perimeter nearest to the nearest existing
|
||||
;; route.
|
||||
(frontage
|
||||
[holding]
|
||||
"TODO: this is WRONG, but will work for now. The frontage should
|
||||
be the side of the perimeter nearest to the nearest existing
|
||||
route."
|
||||
[(first (perimeter holding)) (nth (perimeter holding) 1)])
|
||||
(building-origin [holding]
|
||||
;; TODO: again this is wrong. The default building origin
|
||||
;; should be the right hand end of the frontage when viewed
|
||||
;; from outside the holding.
|
||||
(first (frontage holding)))
|
||||
(building-origin
|
||||
[holding]
|
||||
"TODO: again this is WRONG. The default building origin for rectangular
|
||||
buildings should be the right hand end of the frontage when viewed
|
||||
from outside the holding. But that's not general; celtic-style circular
|
||||
buildings should normally be in the centre of their holdings. So probably
|
||||
building-origin becomes a method of building-family rather than of holding."
|
||||
(first (frontage holding)))
|
||||
ProtoObject)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
(ns cc.journeyman.the-great-game.merchants.merchants
|
||||
"Trade planning for merchants, primarily."
|
||||
(:require [taoensso.timbre :as l :refer [info error spy]]
|
||||
[the-great-game.utils :refer [deep-merge]]
|
||||
[the-great-game.merchants.strategies.simple :refer [move-merchant]]))
|
||||
(:require [cc.journeyman.the-great-game.utils :refer [deep-merge]]
|
||||
[cc.journeyman.the-great-game.merchants.strategies.simple :refer [move-merchant]]
|
||||
[taoensso.timbre :as l]))
|
||||
|
||||
|
||||
(defn run
|
||||
|
@ -10,18 +10,18 @@
|
|||
[world]
|
||||
(try
|
||||
(reduce
|
||||
deep-merge
|
||||
world
|
||||
(map
|
||||
#(try
|
||||
(let [move-fn (or
|
||||
(-> world :merchants % :move-fn)
|
||||
move-merchant)]
|
||||
(apply move-fn (list % world)))
|
||||
(catch Exception any
|
||||
(l/error any "Failure while moving merchant " %)
|
||||
{}))
|
||||
(keys (:merchants world))))
|
||||
deep-merge
|
||||
world
|
||||
(map
|
||||
#(try
|
||||
(let [move-fn (or
|
||||
(-> world :merchants % :move-fn)
|
||||
move-merchant)]
|
||||
(apply move-fn (list % world)))
|
||||
(catch Exception any
|
||||
(l/error any "Failure while moving merchant " %)
|
||||
{}))
|
||||
(keys (:merchants world))))
|
||||
(catch Exception any
|
||||
(l/error any "Failure while moving merchants")
|
||||
world)))
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
plan (select-cargo merchant world)]
|
||||
(l/debug "plan-and-buy: merchant" id)
|
||||
(cond
|
||||
(not (empty? plan))
|
||||
(seq? plan)
|
||||
(let
|
||||
[c (:commodity plan)
|
||||
p (* (:quantity plan) (:buy-price plan))
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
which the object is keyed in the global object list."))
|
||||
|
||||
(defrecord GameObject
|
||||
[id]
|
||||
[id]
|
||||
;; "An object in the world"
|
||||
ProtoObject
|
||||
(id [_] id)
|
||||
(reify-object [object] "TODO: doesn't work yet"))
|
||||
(reify-object [object]
|
||||
"TODO: doesn't work yet"
|
||||
object))
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
(ns cc.journeyman.the-great-game.playroom
|
||||
(require [jme-clj.core :refer :all])
|
||||
(import [com.jme3.math ColorRGBA]))
|
||||
(:require [jme-clj.core :refer [add add-to-root box defsimpleapp fly-cam geo
|
||||
get* get-state load-texture rotate run set*
|
||||
setc set-state start unshaded-mat]])
|
||||
(:import [com.jme3.math ColorRGBA]))
|
||||
|
||||
;; At present this file is just somewhere to play around with jme-clj examples
|
||||
|
||||
(declare app)
|
||||
|
||||
(defn init []
|
||||
(let [cube (geo "jMonkey cube" (box 1 1 1))
|
||||
mat (unshaded-mat)]
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
(:require [clojure.math.numeric-tower :refer [expt sqrt]]
|
||||
[mw-engine.core :refer []]
|
||||
[mw-engine.heightmap :refer [apply-heightmap]]
|
||||
[mw-engine.utils :refer [get-cell in-bounds? map-world scale-world]]
|
||||
[mw-engine.utils :refer [get-cell in-bounds? map-world]]
|
||||
[cc.journeyman.the-great-game.utils :refer [value-or-default]]))
|
||||
|
||||
;; It's not at all clear to me yet what the workflow for getting a MicroWorld
|
||||
|
@ -149,7 +149,7 @@
|
|||
([cell-size x-offset y-offset width height]
|
||||
(get-surface *base-map* *noise-map* cell-size x-offset y-offset width height))
|
||||
([base-map noise-map cell-size x-offset y-offset width height]
|
||||
(let [b (if (seq? base-map) base-map (scale-world (apply-heightmap base-map) 1000))
|
||||
(let [b (if (seq? base-map) base-map (scale-grid (apply-heightmap base-map) 1000))
|
||||
n (if (seq? noise-map) noise-map (apply-heightmap noise-map))]
|
||||
(if (and (in-bounds? b x-offset y-offset)
|
||||
(in-bounds? b (+ x-offset width) (+ y-offset height)))
|
||||
|
|
|
@ -17,6 +17,9 @@
|
|||
},
|
||||
{
|
||||
"path": "../jme-clj"
|
||||
},
|
||||
{
|
||||
"path": "../MicroWorld/mw-engine"
|
||||
}
|
||||
],
|
||||
"settings": {}
|
||||
|
|
Loading…
Reference in a new issue