001  (ns cc.journeyman.the-great-game.buildings.rectangular
002    "Build buildings with a generally rectangular floow plan.
003     
004     ## Motivations
005     
006     Right, the idea behind this namespace is many fold.
007  
008     1. To establish the broad principle of genetic buildings, by creating a
009        function which reproducibly creates reproducible buildings at specified
010        locations, such that different buildings are credibly varied but a
011        building at a specified location is always (modulo economic change) the
012        same.
013     2. Create good rectangular buildings, and investigate whether a single 
014        function can be used to create buildings of more than one family (e.g.
015        can it produce flat roofed, north African style, mud brick houses as
016        well as pitch roofed, half timbered northern European houses?)
017     3. Establish whether, in my current state of fairly severe mental illness,
018        I can actually produce any usable code at all.
019  
020     ## Key factors in the creation of a building
021  
022     ### Holding
023  
024     Every building is on a holding, and, indeed, what I mean by 'building' here
025     may well turn out to be 'the collection of all the permanent structures on
026     a holding. A holding is a polygonal area of the map which does not 
027     intersect with any other holding, but for the time being we'll make the 
028     simplifying assumption that every holding is a rectangular strip, and that
029     'urban' holdings are of a reasonably standard width (see Viking-period 
030     York) and length. Rural holdings (farms, ?wood lots) may be much larger.
031  
032     ### Terrain
033  
034     A building is made of the stuff of the place. In a forest, buildings will 
035     tend to be wooden; in a terrain with rocky outcrops -- normally found on 
036     steep slopes -- stone. On the flat lands where there's river mud, of brick,
037     cob, or wattle and daub. So to build a building we need to know the 
038     terrain. Terrain can be inferred from location but in practice this will 
039     be computationally expensive, so we'll pass terrain in as an argument to
040     the build function.
041  
042     For the time being we'll pass it in simply as a keyword from a defined set
043     of keywords; later it may be a more sophisticated data structure.
044  
045     ### Culture
046  
047     People of different cultures build distinctively different buildings, even
048     when using the same materials. So, in our world, a Japanese wooden house 
049     looks quite different from an Anglo Saxon stave house which looks quite 
050     different from a Canadian log cabin, even though the materials are much the
051     same and the tools available to build with are not much different.
052  
053     Culture can affect not just the overall shape of a building but also its 
054     finish and surface detail. For example, in many places in England, stone
055     buildings are typically left bare; in rural Scotland, typically painted 
056     white or in pastel shades; in Ireland, often quite vivid colours.
057  
058     People may also show religious or cultural symbols on their buildings.
059   
060     For all these reasons, we need to know the culture of the occupant when
061     creating a building. Again, this will initially be passed in as a keyword.
062  
063     ### Craft
064  
065     People in the game world have a craft, and some crafts will require 
066     different features in the building. In the broadly late-bronze-age-to
067     medieval period within which the game is set, residence and  workplace
068     are for most people pretty much the same.
069  
070     So a baker needs an oven, a smith a forge, and so on. All crafts who do
071     some degree retail trade will want a shop front as part of the ground 
072     floor of their dwelling. Merchants and bankers will probably have houses
073     that are a bit more showy than others.
074  
075     Whether the 'genetic buildings' idea will ever really produce suitable
076     buildings for aristons I don't know; it seems more likely that significant
077     strongholds (of which there will be relatively few) should all be hand
078     modelled rather than procedurally generated."
079    (:require [cc.journeyman.the-great-game.holdings.holding :refer [ProtoHolding]]
080              [cc.journeyman.the-great-game.location.location :refer [ProtoLocation]])
081    (:import [org.apache.commons.math3.random MersenneTwister]))
082  
083   
084  (def ^:dynamic *terrain-types* 
085    "Types of terrain which affect building families. TODO: This is a placeholder;
086     a more sophisticated model will be needed."
087    #{:arable :arid :forest :plateau :upland})
088  
089  (def ^:dynamic *cultures*
090    "Cultures which affect building families. TODO: placeholder"
091    #{:ariston :coastal :steppe-clans :western-clans :wild-herd})
092  
093  (def ^:dynamic *crafts*
094    "Crafts which affect building types in the game. See 
095     `Populating a game world`. TODO: placeholder"
096    #{:baker :banker :butcher :chancellor :innkeeper :lawyer :magus :merchant :miller :priest :scholar :smith :weaver})
097  
098  (def ^:dynamic *building-families* 
099    "Families of buildings.
100     
101     Each family has
102     
103     * terrain types to which it is appropriate;
104     * crafts to which it is appropriate;
105     * cultures to which it is appropriate. 
106     
107     Each generated building will be of one family, and will comprise modules 
108     taken only from that family."
109    {:pitched-rectangular {:terrains #{:arable :forest :upland}
110                           :crafts *crafts*
111                           :cultures #{:coastal :western-clans}
112                           :modules []}
113     :flatroof-rectangular {:terrains #{:arid :plateau}
114                            :crafts *crafts*
115                            :cultures #{:coastal}
116                            :modules []}})
117  
118  ;; TODO: So, modules need to contain
119  ;;
120  ;; 1. Ground floor modules, having external doors;
121  ;; 2. Craft modules -- workshops -- which will normally be ground floor (except
122  ;; weavers) and may have the constraint that no upper floor module can cover them;
123  ;; 3. Upper floor modules, having NO external doors (but linking internal doors);
124  ;; 4. Roof modules
125  ;; 
126  ;; There also needs to be an undercroft or platform module, such that the area of 
127  ;; the top of the platform is identical with the footprint of the building, and 
128  ;; the altitude of the top of the platform is equal to the altitude of the 
129  ;; terrain at the heighest corner of the building; so that the actual 
130  ;; building doesn't float in the air, and also so that none of the doors or windows
131  ;; are partly underground.
132  ;;
133  ;; Each module needs to wrap an actual 3d model created in Blender or whatever, 
134  ;; and have a list of optional textures with which that model can be rendered. 
135  ;; So an upper floor bedroom module might have the following renders:
136  ;;
137  ;; 1. Bare masonry - constrained to upland or plateau terrain, and to coastal culture
138  ;; 2. Painted masonry - constrained to upland or plateau terrain, and to coastal culture
139  ;; 3. Half-timbered - not available on plateau terrain
140  ;; 4. Weatherboarded - constrained to forest terrain
141  ;; 5. Brick - constrained to arable or arid terrain
142  ;;
143  ;; of course these are only examples, and also, it's entirely possible to have
144  ;; for example multiple different weatherboard renders for the same module. 
145  ;; There needs to be a way of rendering what can be built above what: for
146  ;; example, you can't have a masonry clad module over a half timbered one, 
147  ;; but you can have a half-timbered one over a masonry one
148  
149  (defn building-family
150    "A building family is essentially a collection of models of building modules
151     which can be assembled to create buildings of a particular structural and
152     architectural style."
153    [terrain culture craft gene]
154    (let [candidates (filter #(and
155                               ((:terrains %) terrain)
156                               ((:crafts %) craft)
157                               ((:cultures %) culture))
158                             (vals *building-families*))]
159      (nth candidates (mod (Math/abs (.nextInt gene)) (count candidates)))))
160  
161  (building-family :arable :coastal :baker (MersenneTwister. 5))
162  
163  (defn build! 
164    "Builds a building, and returns a data structure which represents it. In 
165     building the building, it adds a model of the building to the representation
166     of the world, so it does have a side effect."
167    [holding terrain culture craft size]
168    (if (satisfies? ProtoHolding holding)
169    (let [location (.building-origin holding)
170          gene (MersenneTwister. (int (+ (* (.easting location) 1000000) (.northing location))))
171          family (building-family terrain culture craft gene)]
172    (if 
173     (and (instance? ProtoLocation location) (:orientation location))
174      :stuff
175      :nonsense
176      ))
177      :froboz))
178  
179  ;; (def ol (cc.journeyman.the-great-game.location.location/OrientedLocation. 123.45 543.76 12.34 0.00 {}))
180