This is a very interim commit. Started work on genetic buildings.
Nothing works!
This commit is contained in:
parent
310896cc95
commit
7138c51134
12 changed files with 439 additions and 11 deletions
|
|
@ -1,11 +1,12 @@
|
|||
(ns cc.journeyman.the-great-game.agent.agent
|
||||
"Anything in the game world with agency"
|
||||
(:require [the-great-game.objects.game-object :refer [ProtoObject]]
|
||||
[the-great-game.objects.container :refer [ProtoContainer]]))
|
||||
"Anything in the game world with agency; primarily but not exclusively
|
||||
characters."
|
||||
(:require [cc.journeyman.the-great-game.objects.game-object :refer [ProtoObject]]
|
||||
[cc.journeyman.the-great-game.objects.container :refer [ProtoContainer]]))
|
||||
|
||||
;; hierarchy of needs probably gets implemented here
|
||||
;; I'm probably going to want to defprotocol stuff, to define the hierarchy
|
||||
;; of things in the gameworld; either that or drop to Java, wich I'd rather not do.
|
||||
;;; hierarchy of needs probably gets implemented here
|
||||
;;; I'm probably going to want to defprotocol stuff, to define the hierarchy
|
||||
;;; of things in the gameworld; either that or drop to Java, wich I'd rather not do.
|
||||
|
||||
(defprotocol ProtoAgent
|
||||
"An object which can act in the world"
|
||||
|
|
@ -37,7 +38,7 @@
|
|||
|
||||
(defrecord Agent
|
||||
;; "A default agent."
|
||||
[name home tribe]
|
||||
[name craft home culture]
|
||||
ProtoObject
|
||||
ProtoContainer
|
||||
ProtoAgent
|
||||
|
|
|
|||
168
src/cc/journeyman/the_great_game/buildings/rectangular.clj
Normal file
168
src/cc/journeyman/the_great_game/buildings/rectangular.clj
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
(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]
|
||||
))
|
||||
|
||||
;;; 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;
|
||||
a more sophisticated model will be needed."
|
||||
#{:arable :arid :forest :plateau :upland})
|
||||
|
||||
(def ^:dynamic *cultures*
|
||||
"Cultures which affect building families. TODO: placeholder"
|
||||
#{:ariston :coastal :steppe-clans :western-clans :wild-herd})
|
||||
|
||||
(def ^:dynamic *crafts*
|
||||
"Crafts which affect building types in the game. See
|
||||
`Populating a game world`. TODO: placeholder"
|
||||
#{:baker :banker :butcher :chancellor :innkeeper :lawyer :magus :merchant :miller :priest :scholar :smith :weaver})
|
||||
|
||||
(def ^:dynamic *building-families*
|
||||
{:pitched-rectangular {:terrains #{:arable :forest :upland}
|
||||
:crafts *crafts*
|
||||
:cultures #{:coastal :western-clans}
|
||||
:modules []}
|
||||
:flatroof-rectangular {:terrains #{:arid :plateau}
|
||||
:crafts *crafts*
|
||||
:cultures #{:coastal}
|
||||
:modules []}})
|
||||
|
||||
;; TODO: So, modules need to contain
|
||||
;;
|
||||
;; 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
|
||||
;;
|
||||
;; 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
|
||||
|
||||
(defn building-family
|
||||
"A building family is essentially a collection of models of building modules
|
||||
which can be assembled to create buildings of a particular structural and
|
||||
architectural style."
|
||||
[terrain culture craft gene]
|
||||
(let [candidates (filter #(and
|
||||
((:terrains %) terrain)
|
||||
((:crafts %) craft)
|
||||
((:cultures %) culture))
|
||||
(vals *building-families*))]
|
||||
(nth candidates (mod (Math/abs (.nextInt gene)) (count candidates)))))
|
||||
|
||||
(building-family :arable :coastal :baker (MersenneTwister. 5))
|
||||
|
||||
(defn build!
|
||||
"Builds a building, and returns a data structure which represents it. In
|
||||
building the building, it adds a model of the building to the representation
|
||||
of the world, so it does have a side effect."
|
||||
[holding terrain culture craft size]
|
||||
(if (satisfies? ProtoHolding holding)
|
||||
(let [location (.building-origin holding)
|
||||
gene (MersenneTwister. (int (+ (* (.easting location) 1000000) (.northing location))))
|
||||
family (building-family terrain culture craft gene)]
|
||||
(if
|
||||
(and (instance? ProtoLocation location) (:orientation location))
|
||||
:stuff
|
||||
:nonsense
|
||||
))
|
||||
:froboz))
|
||||
|
||||
;; (def ol (cc.journeyman.the-great-game.location.location/OrientedLocation. 123.45 543.76 12.34 0.00 {}))
|
||||
|
||||
42
src/cc/journeyman/the_great_game/holdings/holding.clj
Normal file
42
src/cc/journeyman/the_great_game/holdings/holding.clj
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
(ns cc.journeyman.the-great-game.holdings.holding
|
||||
(:require [cc.journeyman.the-great-game.agent.agent :refer [ProtoAgent]]
|
||||
[cc.journeyman.the-great-game.objects.container :refer [ProtoContainer]]
|
||||
[cc.journeyman.the-great-game.objects.game-object :refer [ProtoObject]]
|
||||
;; [cc.journeyman.the-great-game.location.location :refer [OrientedLocation]]
|
||||
[cc.journeyman.the-great-game.world.routes :refer []]))
|
||||
|
||||
;;; A holding is a polygonal area of the map which does not
|
||||
;;; intersect with any other holding, or with any road or water feature. 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.
|
||||
|
||||
(defprotocol ProtoHolding
|
||||
(frontage
|
||||
[holding]
|
||||
"Returns a sequence of two locations representing the edge of the polygon
|
||||
which defines this holding which is considered to be the front.")
|
||||
(building-origin
|
||||
[holding]
|
||||
"Returns an oriented location - normally the right hand end of the
|
||||
frontage, for an urban holding - from which buildings on the holding
|
||||
should be built."))
|
||||
|
||||
(defrecord Holding [perimeter holder]
|
||||
;; Perimeter should be a list of locations in exactly the same sense as a
|
||||
;; route in `cc.journeyman.the-great-game.world.routes`. Some sanity checking
|
||||
;; 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.
|
||||
[(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)))
|
||||
ProtoObject)
|
||||
47
src/cc/journeyman/the_great_game/location/location.clj
Normal file
47
src/cc/journeyman/the_great_game/location/location.clj
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
(ns cc.journeyman.the-great-game.location.location)
|
||||
|
||||
;;; There's probably conflict between this sense of a reified location and
|
||||
;;; the simpler sense of a location described in
|
||||
;;; `cc.journeyman.the-great-game.world.location`, q.v. This needs to
|
||||
;;; be resolved!
|
||||
|
||||
(defprotocol ProtoLocation
|
||||
(easting [location]
|
||||
"Return the easting of this location")
|
||||
(northing [location] "Return the northing of this location")
|
||||
(altitude [location]
|
||||
"Return the absolute altitude of this location, which may be
|
||||
different from the terrain height at this location, if, for
|
||||
example, the location is underground or on an upper floor.")
|
||||
(terrain-altitude [location]
|
||||
"Return the 'ground level' (altitude of the terrain)
|
||||
at this location given this world. TODO: possibly
|
||||
terrain-altitude should be a method of the world.")
|
||||
(settlement [location]
|
||||
"Return the settlement record of the settlement in this world
|
||||
within whose parish polygon this location exists, or if none
|
||||
whose centre (inn location) is closest to this location"))
|
||||
|
||||
|
||||
(defrecord Location [^Double easting ^Double northing ^Double altitude world]
|
||||
ProtoLocation
|
||||
(easting [l] (:easting l))
|
||||
(northing [l] (:northing l))
|
||||
(altitude [l] (:altitude l))
|
||||
(terrain-altitude [l] 0.0) ;; TODO
|
||||
(settlement [l] :tchahua))
|
||||
|
||||
(defrecord OrientedLocation
|
||||
;; "Identical to a Location except having, additionally, an orientation"
|
||||
[^Double easting ^Double northing ^Double altitude ^Double orientation world]
|
||||
ProtoLocation
|
||||
(easting [l] (:easting l))
|
||||
(northing [l] (:northing l))
|
||||
(altitude [l] (:altitude l))
|
||||
(terrain-altitude [l] 0.0) ;; TODO
|
||||
(settlement [l] :tchahua)) ;; TODO
|
||||
|
||||
;; (.settlement (OrientedLocation. 123.45 543.76 12.34 0.00 {}))
|
||||
|
||||
|
||||
;; (OrientedLocation. 123.45 543.76 12.34 0.00 {})
|
||||
68
src/cc/journeyman/the_great_game/playroom.clj
Normal file
68
src/cc/journeyman/the_great_game/playroom.clj
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
(ns cc.journeyman.the-great-game.playroom
|
||||
(require [jme-clj.core :refer :all])
|
||||
(import [com.jme3.math ColorRGBA]))
|
||||
|
||||
;; At present this file is just somewhere to play around with jme-clj examples
|
||||
|
||||
(defn init []
|
||||
(let [cube (geo "jMonkey cube" (box 1 1 1))
|
||||
mat (unshaded-mat)]
|
||||
(set* mat :texture "ColorMap" (load-texture "textures/Monkey.jpg"))
|
||||
(set* cube :material mat)
|
||||
(add-to-root cube)
|
||||
{:cube cube}))
|
||||
|
||||
;; Let's create simple-update fn with no body for now.
|
||||
(defn simple-update [tpf]
|
||||
(let [{:keys [cube]} (get-state)]
|
||||
(rotate cube 0 (* 2 tpf) 0)))
|
||||
|
||||
|
||||
;; Kills the running app var and closes its window.
|
||||
;; (unbind-app #'app)
|
||||
|
||||
;; We define the `app` var.
|
||||
(defsimpleapp app
|
||||
:opts {:show-settings? false
|
||||
:pause-on-lost-focus? false
|
||||
:settings {:title "My JME Game"
|
||||
:load-defaults? true
|
||||
:frame-rate 60
|
||||
:width 800
|
||||
:height 600}}
|
||||
:init init
|
||||
:update simple-update)
|
||||
|
||||
(start app)
|
||||
|
||||
;; Reinitialises the running app
|
||||
;;(run app
|
||||
;; (re-init init))
|
||||
|
||||
;; 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))
|
||||
|
||||
|
||||
;; Updates the app
|
||||
(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)))
|
||||
|
||||
;; 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)))
|
||||
Loading…
Add table
Add a link
Reference in a new issue