Compare commits
13 commits
Author | SHA1 | Date | |
---|---|---|---|
|
cd5b7e87be | ||
|
4b8570916b | ||
|
06a2a17528 | ||
|
2bb7e1a87c | ||
|
e6d892a594 | ||
|
9a7ec957ca | ||
|
fd4a5bb8cc | ||
|
bf9078142b | ||
|
3ff5a345f1 | ||
|
9aa161725b | ||
|
a8a9a764e4 | ||
|
dcf79bca7a | ||
|
c142aad2d8 |
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -60,3 +60,4 @@ src/cc/journeyman/the_great_game/cloverage.clj
|
|||
resources/jme3/images/
|
||||
resources/jme3/textures/
|
||||
resources/polyhaven/textures/
|
||||
workspace.code-workspace
|
||||
|
|
176
doc/3D-formats.md
Normal file
176
doc/3D-formats.md
Normal file
|
@ -0,0 +1,176 @@
|
|||
# 3D file formats
|
||||
|
||||
I'm going to be doing a lot with programatically manipulated models. Therefore there's a benefit to me in using a file format which is human-readable, and also easily parsed. Compactness is also a virtue, but it's a virtue I can achieve by compressing human readable files, I think.
|
||||
|
||||
Loading time is an issue, but I will be loading relatively few models and manipulating them in memory to produce large numbers of variants, rather than loading a new model for every asset I wish to place. So both from the point of view of total disk space and from the point of view of performance, I think that formats which are optimised more towards my needs as a developer than to raw performance or storage size are probably justified.
|
||||
|
||||
Obviously jMonkeyEngine's own `.j3o` format is something I can parse -- because I have the native jMonkeyEngine libraries to do it -- but it's not something I can inspect or hand edit, so I'm unwilling at this stage to use it. As I understand it, it's a file of serialised Java objects, which, if so, would make it relatively efficient to load.
|
||||
|
||||
## XML formats
|
||||
|
||||
XML formats are easy to parse; they're also reasonably easy to edit both as text files and as structured files. So my preference is to use them as a starting point for search. The obvious XML formats are
|
||||
|
||||
1. [3DXML](https://en.wikipedia.org/wiki/3DXML), a proprietary format owned by Dassault Systèmes;
|
||||
2. [Collada](https://www.khronos.org/collada/), an open format apparently seen primarily as an unlossy interchange format between 3d applications;
|
||||
3. [X3D](https://www.web3d.org/x3d/what-x3d/), an open format seen as the successor to (and much more prolix than) VRML;
|
||||
4. Ogre 3D, a format designed for the [Ogre 3D game engine](https://www.ogre3d.org/) and now widely used in the jMonkeyEngine community, but for which I can find no user-oriented documentation.
|
||||
|
||||
## JSON-based formats
|
||||
|
||||
JSON is also easy to parse and to edit; the [glTF 2.0](https://www.khronos.org/gltf/) standard, in its JSON/ASCII representation, is such a format.
|
||||
|
||||
## Other text formats
|
||||
|
||||
[VRML](https://en.wikipedia.org/wiki/VRML) isn't either XML or JSON, but it looks reasonably easy to parse.
|
||||
|
||||
## Features
|
||||
|
||||
| Name | XML | JSON | Blender | MakeHuman | jME3 | Notes |
|
||||
| -------------------------------------------- | ------- | ------- | ------------------------------------------------------------ | --------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||
| [3DXML](https://en.wikipedia.org/wiki/3DXML) | ✓ | | [Unsupported](https://blenderartists.org/t/3dxml-importer/469975/2) | No | No | Proprietary; apparently, engineering oriented |
|
||||
| [Collada](https://www.khronos.org/collada/) | ✓ | | Built in importer/exporter | Exporter | [No](https://hub.jmonkeyengine.org/t/collada-io/46406) | Prolix, but sort-of interpretable and manageable. |
|
||||
| [X3D](https://www.web3d.org/x3d/what-x3d/) | ✓ | | Built in importer/exporter | No | No | |
|
||||
| [Ogre 3D](https://www.ogre3d.org/) | ✓ | | [Unsupported](https://github.com/OGRECave/blender2ogre) | Exporter | [built in importer](https://javadoc.jmonkeyengine.org/v3.6.1-stable/com/jme3/scene/plugins/ogre/package-summary.html) | |
|
||||
| [glTF 2.0](https://www.khronos.org/gltf/) | | ✓ | Built in importer/exporter | No | [built in importer](https://javadoc.jmonkeyengine.org/v3.6.1-stable/com/jme3/scene/plugins/gltf/package-summary.html) | On inspection, the glTF 2.0 files generated by Blender are thoroughly inscrutable. Although they are technically text files, they're essentially very thin wrappers around ascii-coded binary blobs. This doesn't look usable to me. |
|
||||
| [VRML](https://en.wikipedia.org/wiki/VRML) | | | Apparently accepted by the X3D importer; no exporter | No | No | I couldn't make import of a sample file into Blender work. The import completed with no errors, but no objects appeared in the scene. |
|
||||
|
||||
## Discussion
|
||||
|
||||
I did not investigate 3DXML, because I'm not going to sign up to even a free licence from an armaments company.
|
||||
|
||||
Of the rest: I'm pretty disappointed.
|
||||
|
||||
### glTF
|
||||
|
||||
**glTF** might as well be a binary format; it's unusable for my purposes.
|
||||
|
||||
### X3D
|
||||
|
||||
**X3D** export of the simple cube from Blender results in a file which is readable, but which does not have explicit vertices or edges. Instead it has an attribute whose value is a string representation of a sequence of 24 numbers:
|
||||
|
||||
```xml
|
||||
<Coordinate DEF="coords_ME_Cube"
|
||||
point="1.000000 1.000000 1.000000 1.000000 1.000000 -1.000000 1.000000 -1.000000 1.000000 1.000000 -1.000000 -1.000000 -1.000000 1.000000 1.000000 -1.000000 1.000000 -1.000000 -1.000000 -1.000000 1.000000 -1.000000 -1.000000 -1.000000 "/>
|
||||
```
|
||||
|
||||
I'm confidently assuming that that sequence is expected to be read as a set of six triples, each triple representing a vertex with `x, y, z` coordinates; but it's not at all clear to me how edges and faces are encoded.
|
||||
|
||||
Furthermore, when you reimport an X3D file exported by Blender back into Blender you get nothing visible (and no error message). This is exactly the same as what you get when you import a VRML file, which does not raise confidence.
|
||||
|
||||
### Collada
|
||||
|
||||
**Collada** is a little better in that it explicitly says how many numbers are in the array, and does not present them as an attribute but as data; additionally, it has information on how to decode that data into tuples:
|
||||
|
||||
```xml
|
||||
<source id="Cube-mesh-positions">
|
||||
<float_array id="Cube-mesh-positions-array" count="24">1 1 1 1 1 -1 1 -1 1 1 -1 -1 -1 1 1 -1 1 -1 -1 -1 1 -1 -1 -1</float_array>
|
||||
<technique_common>
|
||||
<accessor source="#Cube-mesh-positions-array" count="8" stride="3">
|
||||
<param name="X" type="float"/>
|
||||
<param name="Y" type="float"/>
|
||||
<param name="Z" type="float"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
|
||||
```
|
||||
|
||||
and the **vertices** are declared as being the points in this array:
|
||||
|
||||
```xml
|
||||
<vertices id="Cube-mesh-vertices">
|
||||
<input semantic="POSITION" source="#Cube-mesh-positions"/>
|
||||
</vertices>
|
||||
|
||||
```
|
||||
|
||||
but again there's nothing obvious to indicate which vertices are joined by **edges**. There is an array of six normals, which presumably imply the faces of the cube, but that's a little sketchy. There are also **triangles**, declared as follows:
|
||||
|
||||
```xml
|
||||
<triangles material="Material-material" count="12">
|
||||
<input semantic="VERTEX" source="#Cube-mesh-vertices" offset="0"/>
|
||||
<input semantic="NORMAL" source="#Cube-mesh-normals" offset="1"/>
|
||||
<input semantic="TEXCOORD" source="#Cube-mesh-map-0" offset="2" set="0"/>
|
||||
<p>4 0 0 2 0 1 0 0 2 2 1 3 7 1 4 3 1 5 6 2 6 5 2 7 7 2 8 1 3 9 7 3 10 5 3 11 0 4 12 3 4 13 1 4 14 4 5 15 1 5 16 5 5 17 4 0 18 6 0 19 2 0 20 2 1 21 6 1 22 7 1 23 6 2 24 4 2 25 5 2 26 1 3 27 3 3 28 7 3 29 0 4 30 2 4 31 3 4 32 4 5 33 0 5 34 1 5 35</p>
|
||||
</triangles>
|
||||
```
|
||||
|
||||
H'mmm... Twelve triangles makes sense for six square faces, but there are 108 numbers in that `<p>` element, which is eighteen numbers per triangle; and since the highest number is 35, they're not indices into either the `Cube-mesh-vertices` (8) or the `Cube-mesh-normals` (6) arrays, so that implies they are indices into `Cube-mesh-map-0`, which *does* have 36 entries...
|
||||
|
||||
```xml
|
||||
<source id="Cube-mesh-map-0">
|
||||
<float_array id="Cube-mesh-map-0-array" count="72">0.875 0.5 0.625 0.75 0.625 0.5 0.625 0.75 0.375 1 0.375 0.75 0.625 0 0.375 0.25 0.375 0 0.375 0.5 0.125 0.75 0.125 0.5 0.625 0.5 0.375 0.75 0.375 0.5 0.625 0.25 0.375 0.5 0.375 0.25 0.875 0.5 0.875 0.75 0.625 0.75 0.625 0.75 0.625 1 0.375 1 0.625 0 0.625 0.25 0.375 0.25 0.375 0.5 0.375 0.75 0.125 0.75 0.625 0.5 0.625 0.75 0.375 0.75 0.625 0.25 0.625 0.5 0.375 0.5</float_array>
|
||||
<technique_common>
|
||||
<accessor source="#Cube-mesh-map-0-array" count="36" stride="2">
|
||||
<param name="S" type="float"/>
|
||||
<param name="T" type="float"/>
|
||||
</accessor>
|
||||
</technique_common>
|
||||
</source>
|
||||
```
|
||||
|
||||
which is six entries per face. Which sort of makes sense. But the numbers make no obvious sense to me. There are nine distinct values:
|
||||
|
||||
```clojure
|
||||
user=> (def s (set [0.875 0.5 0.625 0.75 0.625 0.5 0.625 0.75 0.375 1 0.375 0.75 0.625 0 0.375 0.25 0.375 0 0.375 0.5 0.125 0.75 0.125 0.5 0.625 0.5 0.375 0.75 0.375 0.5 0.625 0.25 0.375 0.5 0.375 0.25 0.875 0.5 0.875 0.75 0.625 0.75 0.625 0.75 0.625 1 0.375 1 0.625 0 0.625 0.25 0.375 0.25 0.375 0.5 0.375 0.75 0.125 0.75 0.625 0.5 0.625 0.75 0.375 0.75 0.625 0.25 0.625 0.5 0.375 0.5]))
|
||||
#'user/s
|
||||
user=> s
|
||||
#{0 0.125 0.25 0.5 0.625 0.375 0.75 0.875 1}
|
||||
user=> (sort s)
|
||||
(0 0.125 0.25 0.375 0.5 0.625 0.75 0.875 1)
|
||||
```
|
||||
|
||||
But there's no obvious pattern to how frequently these values occur:
|
||||
|
||||
```clojure
|
||||
user=> (map (fn [i] (count (filter (fn [j] (= i j)) all-values))) s)
|
||||
(3 3 6 12 15 15 12 3 3)
|
||||
```
|
||||
|
||||
So... it's not obvious to me how I extract a piece of solid geometry, namely a cube with sides of length 2, centred on the origin, from this data. I know it can be done, because when Blender reimports the file it not only renders a cube but recognises it as a cube; but it isn't trivial.
|
||||
|
||||
### Ogre 3D
|
||||
|
||||
**Ogre 3D** is a lot clearer. Here is (part of) its attempt at saving the cube:
|
||||
|
||||
```xml
|
||||
<mesh>
|
||||
<sharedgeometry vertexcount="24">
|
||||
<vertexbuffer colours_diffuse="False" normals="true" positions="true" tangent_dimensions="0" tangents="False" texture_coords="1">
|
||||
<vertex>
|
||||
<position x="1.000000" y="1.000000" z="-1.000000"/>
|
||||
<normal x="0.000000" y="1.000000" z="-0.000000"/>
|
||||
<texcoord u="0.625000" v="0.500000"/>
|
||||
</vertex>
|
||||
<vertex>
|
||||
<position x="-1.000000" y="1.000000" z="1.000000"/>
|
||||
<normal x="0.000000" y="1.000000" z="-0.000000"/>
|
||||
<texcoord u="0.875000" v="0.250000"/>
|
||||
</vertex>
|
||||
...
|
||||
</vertexbuffer>
|
||||
</sharedgeometry>
|
||||
<submeshes>
|
||||
<submesh material="Material" operationtype="triangle_list" use32bitindexes="False" usesharedvertices="true">
|
||||
<faces count="12">
|
||||
<face v1="0" v2="1" v3="2"/>
|
||||
<face v1="3" v2="4" v3="5"/>
|
||||
...
|
||||
</faces>
|
||||
</submesh>
|
||||
</submeshes>
|
||||
<submeshnames>
|
||||
<submesh index="0" name="Material"/>
|
||||
</submeshnames>
|
||||
</mesh>
|
||||
```
|
||||
|
||||
Nothing in this explicitly says it's a cube. But where we have two triangles with a common edge and a common normal, we know they form part of the same face; and, given that each of the distinct normals are either at right angles to, or in opposition to, each of the others, the boxiness is easily inferred. Finally, given all the edges are of the same length, we have a cube.
|
||||
|
||||
Although the [Ogre import/export add on](https://github.com/OGRECave/blender2ogre) is not supported by Blender, an exported cube can be successfully reimported into Blender. However, although Blender can export the meshes of a model to Ogre format successfully, it fails to export the skeleton. However the MakeHuman Ogre exporter does successfully export the skeleton.
|
||||
|
||||
The only documentation for Ogre 3D XML that I can find is [two DTDs here](https://github.com/OGRECave/ogre/tree/master/Tools/XMLConverter/docs), but, in fact, that is what I most need.
|
||||
|
||||
## Summary
|
||||
|
||||
Generally, this is disappointing. I may need to rethink my approach. But, although I was initially prejudiced against Ogre 3D because of its relative obscurity and lack of user-oriented documentation, it is probably the best of the bunch.
|
|
@ -1,130 +0,0 @@
|
|||
# Biomes and ecology (unfinished)
|
||||
*The motivation for this document was to explain the mulberry trees in the Tcha valley, and think about why Tchahua is especially a centre for the silk trade*
|
||||
|
||||
## Broader geography
|
||||
|
||||
The broader geography of the world is not a matter for this document, but TODO: there isn't yet a document which usefully describes it, and there needs to be.
|
||||
|
||||
|
||||
## Biomes relevant at this stage
|
||||
|
||||
### 1. Steppe
|
||||
|
||||
The centre of the continent is the steppe; it is generally too arid for forest growth, and is therefore scrub and grassland. There is one principal river system, which feeds into a marshland in the south, from which the water then goes underground beneath the limestone plateau to become the Tcha and Sind rivers. In late summer there's little water in the river, and few other waterholes. Antelope, camels, horses, goats, possibly sheep are native to the steppe, and there are probably something like leopards which predate on them, but I haven't fleshed it out.
|
||||
|
||||
Big dragons don't hunt on the steppe because they can't take off from flat ground, but smaller dragons may do so.
|
||||
|
||||
Settled by the steppe tribes, who are nomadic herders, extremely warlike but not technically highly developed. They are the game world's principle horse breeders. Basically in the game as I'm working on it at present, the player cannot go north across the steppe because the steppe tribes are too hostile.
|
||||
|
||||
A single major road, the Caravan Road, runs north to south across the steppe. There were in the past fortified caravanserrais along the length of the road, established and protected by Hans'hua, but they have been progressively overrun and destroyed by the steppe tribes and are now ruinous. Only one remains: the North Inn, just below the northern slope of the plateau. There is some limited horticulture on land close to the South Inn, supplying markets in Hans'hua.
|
||||
|
||||
### 2. Plateau
|
||||
|
||||
The limestone plateau runs along the whole of the southern edge of the steppe, from the western massif to the rim of the crater which forms The Great Place. It is a landscape of clints and grykes, on which nothing grows, and on which there is no water. It is about four day's journey by fast horse from north to south. The caravan road crosses the plateau from the North Inn to another caravanserrai, the South Inn, located in the north end of the Tcha valley. Because of the dense chaotic pattern of clints and grykes and the lack of accessible water, it is effectively impossible to cross the plateau other than by the caravan road, or by another path to the extreme east of the plateau, where it abuts the mountains of the Rim.
|
||||
|
||||
#### 2.1 Hans'hua
|
||||
|
||||
There is one city, Hans'hua, on the caravan road about half way across the plateau, where wind-pumps lift water from the underground river. Apart from this one city, nothing lives on the plateau. Migrating birds cross it, and that is all.
|
||||
|
||||
The city is small, walled, and run as an extreme neoliberal oligarchy; the city's main industry is maintaining the wind pumps, and its entire income is from tolls on caravans passing along the caravan road. This has been, and is still, extremely lucrative, but it is obvious both to the long distance merchants and to the oligarchs that the new ships are going to make the caravans too slow, too risky and too expensive to compete, and that as more ships are built, traffic on the caravan road will dwindle.
|
||||
|
||||
### 3. Massif
|
||||
|
||||
There's a granite intrusion which forms the entire western coast of the continent. It's geologically old and consequently the hills, though high, are rounded rather than jagged; at the southern end of the range (which is the only part that's in the least fleshed out yet) they're not snow covered in summer. As the prevailing winds are westerly, this massif intercepts most of the rain, which is why the steppe is arid.
|
||||
|
||||
Consequently it's pretty thoroughly forested, and the southern parts of it are mainly broadleaf forests including high quality hardwoods and many fruiting trees. Understory typical of mediterranean littoral forests, about which I don't really know enough.
|
||||
|
||||
Deer, cattle, pigs, wolves, leopards, badgers, squirrels… masses of birds of all appropriate types.
|
||||
|
||||
Because it's an old granite intrusion, the soil in the valleys is largely clay. There are mineral rich veins with a considerable range of minerals, but, obviously, not all in the same place.
|
||||
|
||||
Settled by the Western Clans, a negroid people living mainly in small isolated villages in the forest, with mostly limited agriculture.
|
||||
|
||||
#### 3.1 Northern massif
|
||||
|
||||
I haven't yet fleshed this out, but there are probably permanent snows and the forests are probably coniferous. It's my current working assumption that the new great ships are built from old growth conifers, taken from forests in the northern massif; but as I say this is not yet fleshed out.
|
||||
|
||||
The northern culture have developed very high quality ceramics using clay from the massif, including stonewares and porcelaines. I think the same clays also exist in the south of the massif, but the technology for producing high quality ceramics does not exist there. The northerners are also making high quality steels from magnetite and haematite from the massif. Whether these ores exist in the south I don't yet know.
|
||||
|
||||
#### 3.2 Dor
|
||||
|
||||
The northernmost of the western clans, the Dor, live in the central massif north of Andale, but apart from the fact that they exist and they're there, I don't yet really know much.
|
||||
|
||||
#### 3.3 Andale
|
||||
|
||||
The river An rises in the east of the massif near the south-west corner of the steppe, west of where the village and market of Dawnhold now stand, and flows more or less due westward. There are two major drops in the river's course, the upper a day's travel east of Silverhold, which is an actual fall of at least six metres, and the lower at Anghold. Between Anghold and Silverhold the river is navigable by small shallow draught boats; west of Anghold it is navigable down to the sea at Anmouth.
|
||||
|
||||
There are freshwater and migratory fish in the river, and fishing is a source of protein and livelihood the whole length of the valley.
|
||||
|
||||
The valley is largely forested. Apart from wild animals, domestic cattle and pigs are herded in the forest. Trees include alder, almond, apple, apricot, ash, beech, birch, cherry, chestnut, hazel, holly, lime, maple, mulberry, oak, orange, pear, walnut, yew.
|
||||
|
||||
##### 3.3.1 Dawnhold
|
||||
|
||||
Dawnhold isn't strictly geographically in Andale — it's east of, on the steppe side of, the watershead, but it marks the eastern border of the lands settled by clan An. There's an annual market, a village, and a garrisoned fortification to deter raids by the steppe tribes.
|
||||
|
||||
##### 3.3.2 Silverhold
|
||||
|
||||
Small town serving the only significant silver mine in the world. A tributary flows in from the north here, but I know nothing about it yet. There is a major fortification/refinery/treasury. All around Silverhold, right up to the headwaters of the An and right down to Anghold, the valley is forested with only small clearings round villages, which are mainly close to the river.
|
||||
|
||||
Many other metals — certainly inluding lead, tin, and small quantities of gold, probably not copper — come out of the mines at Silverhold.
|
||||
|
||||
The An produce enough ferrous metals for their own tools and weapons, but their iron smelting technology is not advanced and they don't export iron or iron products. They produce eathernware ceramics for domestic consumption. They produce leather and linen, and textiles from nettle fibres. They produce timber, which is their principal building material, but they don't export it. In practice their major export is silver coinage.
|
||||
|
||||
##### 3.3.3 Longwater
|
||||
|
||||
Longwater is a long, narrow lake, like Loch Lomond, on a tributary which flows into the An from the south, joining upstream from Anghold. There is no major nucleated settlement on Longwater, but there are sufficient small villages and hamlets on its banks to form an identifiable settlement cluster. Small boats can make it downstream from Longwater from the An and back, probably with some degree of portage around rapids. There's a pass over from the south of the Longwater valley to Gor territory, but it's high, difficult, and not much used. The whole of the Longwater valley is broadleaf forest.
|
||||
|
||||
##### 3.3.4 Anghold
|
||||
|
||||
There's a small town, market and fortification — Anghold — on the south bank of the An, just above first cataract, where boats are portaged up from the lower river to the middle reach. Downstream from Anghold the river is wider, slower and more meandering, with marshy banks. The valley west of Anghold, especially on the southern side, is also more populated, with more of the forest cleared and more arable agriculture.
|
||||
|
||||
##### 3.3.5 Anmouth
|
||||
|
||||
The An meets the sea at Anmouth, where there is a deep harbour at a bend in the river just east of a long estuary, There is a bar, making it dangerous to enter the harbour in bad weather, and the whole estuary is pretty exposed to western storms, although there may be some islands providing some shelter for emergency anchorages — I don't have that level of detail yet. Certainly the big new ships do not yet call in here, but could.
|
||||
|
||||
There are farming and sea-fishing villages down both sides of the estuary. There is no tradition of ship building, however.
|
||||
|
||||
#### 3.4 Gor
|
||||
|
||||
Clan Gor occupy the south-western peninsula of the continent, and the south slope of the massif, east almost as far as the Tcha valley. Their land is forested with a similar mix of trees to Andale. They have no major rivers, but several minor ones. They live mainly in coastal villages, and sea fishing is a major economic activity. They have no deep water ports.
|
||||
|
||||
In addition they do mine iron, and they have exported swords, but the market for their swords is being undercut by better crucible steel swords from the north now being imported into the Cities of the Coast by the new ships. Similarly, the Gor used to export earthenware, but that too is now being undercut by stonewares and porcelaines from the north.
|
||||
|
||||
Because of a history of being victims of raiding from the Cities of the Coast, the Gor maintain a fortified eastern border along the line of hills to the west of the Tcha valley. Nevertheless they have mostly good trading relationships with Tchahua. In particular they export large quantities of raw and spun silk, and some woven silk cloth, to Tchahua.
|
||||
|
||||
I don't yet have nearly a clear enough picture of the organisation and layout of the Gor lands, but their major stronghold and administrative centre must be to the east. While they traditionally had the communist and democratic culture of the other Western Clans, one family have become dominant and have become effectively hereditary leaders, influenced by the cultures to their east. However the leading family do not self-identify as aristons.
|
||||
|
||||
### 4. Coast
|
||||
|
||||
"The Coast" is the name given to the southern littoral of the continent, west of the Great Place and east of the Massif. It's limestone, with deeply cut, steep sided valleys separated by high, arid uplands, with scrubby vegetation, grazed by domestic sheep and both domestic and wild goats.
|
||||
|
||||
The native culture were peaceable, communistic agriculturalists, not greatly different from the Western Clans. However some several hundred years ago they were invaded by a warrior group from the steppe tribes, who established themselves as a military aristocracy — the Aristae — and started to build cities — and impose taxes onto the peasantry, forcing them into a more or less cash oriented economy.
|
||||
|
||||
The valleys were once forested, but the central valleys, which were in any case rather dryer and where the Aristae first settled and established cities, are now mostly cleared, and are a mix of pastoral and arable, with considerable viticulture.
|
||||
|
||||
#### 4.1 Tcha valley
|
||||
|
||||
The Tcha is the westernmost — and largest — river of the coast. It emerges from under the plateau at a pool under the South Tower marking the southern limit of Hans'hua territory and runs south more or less along the divide between the granite to the west and the limestone to the east. It is still largely forested, partly because it is relatively recently occupied by the Aristae, but partly because of the growth of the silk industry. This has led to some forested areas, especially near the navigable reaches of the river, being converted into mulberry orchards. However, there's still a great deal of mixed forest, and the majority of mulberry leaves for feeding to silk worms are gathered from natural forest.
|
||||
|
||||
A road branches off from the main Caravan Road at the South Inn and runs down the eastern side of the valley, to a ferry across the Sind river, where it joins the Tcha as a tributary, at the village helpfully known as Sind Ferry, and thence to Tchahua.
|
||||
|
||||
Mulberries, by-products of the silk industry, are used in the production of brandy. Mulberry wine is produced in villages in the forest, and transported down river to a distillery at Sind Ferry, where it is distilled. Some mulberry wine may be sold in Tchahua for drinking as wine (and it is certainly drunk in the villages), but it is generally considered inferior to grape wine.
|
||||
|
||||
There is some arable and mixed agriculture, mainly towards the southern end of the valley on the western (less steep) side, although this side is also largely forested.
|
||||
|
||||
##### 4.1.1 Tchahua
|
||||
|
||||
The city of Tchahua lies on the east bank of the river at the head of its estuary, and has deep water — the only really usable deep water port on the coast, being not only the largest river but also the least silted. Until quite recently it had been a small provincial silk weaving city, nominally independent but in fact paying tribute to both Sinhua to its east and the Gor to its west, in order to avoid being formally conquered by either.
|
||||
|
||||
There's a multi-span bridge here — I think a pontoon bridge — of which the eastern most span is a drawbridge which can be lifted into a fortified gateway on the eastern (Tchahua) shore. There is a fishing industry, but as the eastern side
|
||||
|
||||
Industries are silk weaving and dying, and fishing. Very recently, a new deep water quay has been constructed and the first large ships have begun to call. It is obvious that the city is going to become much more important as a strategic market and transport hub, but that has only just begun to have effect.
|
||||
|
||||
### 4.2 Sind valley
|
||||
|
||||
#### 4.2.1 Sinhua
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -25,11 +25,11 @@ A `heightmap` is a raster image of the world, such that the intensity in which a
|
|||
|
||||
#### Holding
|
||||
|
||||
A `holding` is a polygon 'owned' by an `actor` on which are built appropriate building units representing the `actors` craft and status.
|
||||
A `holding` is a polygon 'owned' by an `actor` on which are built appropriate building units representing the `actor`'s craft and status.
|
||||
|
||||
#### Location
|
||||
|
||||
A `location` value is a sequence comprising at most the x/y coordinate location and the ids of the settlement and region (possibly hierarchically) that contain the location. If the x/y is not local to the home of the receiving agent, they won't remember it and won't pass it on; if any of the ids are not interesting, they won't be passed on. So location information will degrade progressively as the item is passed along.
|
||||
A `location` value is a sequence comprising at most the x/y or x/y/z coordinate location and the ids of the settlement and region (possibly hierarchically) that contain the location. If the :z coordinate is not supplied the terrain surface hieght at that x/y location will be assumed. If the x/y is not local to the home of the receiving agent, they won't remember it and won't pass it on; if any of the ids are not interesting, they won't be passed on. So location information will degrade progressively as the item is passed along.
|
||||
|
||||
It is assumed that the `:home` of a character is a location in this sense.
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Division of tasks between server and client
|
||||
# Division of tasks between server and client (unfinished)
|
||||
|
||||
An alternative nomentclature I may use for this dichotomy would be _planner_ and _performer_; it would be the same dichotomy. 'Planner' and 'server' are synonyms; 'performer' and 'client' are synonyms.
|
||||
|
||||
|
|
72
doc/Draft-algorithm-functional-physics-engine.md
Normal file
72
doc/Draft-algorithm-functional-physics-engine.md
Normal file
|
@ -0,0 +1,72 @@
|
|||
# Sketch for an algorithm for a pure-functional physics engine
|
||||
|
||||
What a physics engine needs to do is, at each step
|
||||
|
||||
1. Take a collection of bodies;
|
||||
2. For every pair of bodies, compute the change in velocity of each consequent on their interaction;
|
||||
3. For each body, merge the changes in velocity found in step two into one change in velocity;
|
||||
4. For each body, update the position of the body.
|
||||
|
||||
Now, in practice, for simulations in a terrestrial environment, the largest interaction any of the other bodies constantly has is that with the planet in the form of gravity; and, gravity of the planet is so much greater than that of any other body in the environment that the gravitational attraction of the other bodies to each other can be ignored; and finally, the difference in mass between the planet and any other of the bodies is such that changes to the velocity of the planet can effectively ignored. So we can modify that to
|
||||
|
||||
1. Take a collection of bodies excepting the planet;
|
||||
2. For each pair of bodies *including the planet*, compute as vectors changes in velocity consequent on collisions between them (but the change in velocity of the planet will always be deemed to be zero);
|
||||
3. For each body, compute as a vector the change in velocity consequent on the gravitational attraction of the planet;
|
||||
4. For each body, compute as a vector the change in velocity consequent on the friction of the medium through which it is moving;
|
||||
5. For each body, merge the vectors computed above with the body's initial velocity to produce a new velocity vector.
|
||||
|
||||
OK so far?
|
||||
|
||||
So that looks something like
|
||||
|
||||
```clojure
|
||||
(require [clojure.math.combinatorics :refer [combinations]])
|
||||
|
||||
(defn physics-tick
|
||||
"Compute the change of velocity to each of these `objects` in one tick."
|
||||
[objects]
|
||||
(pmap merge-vectors
|
||||
(pmap apply-friction
|
||||
(pmap apply-gravity
|
||||
(merge-collisions
|
||||
(remove nil? (pmap collide (combinations objects 2)))
|
||||
objects
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
```
|
||||
Where:
|
||||
|
||||
`collide` is a function which takes two objects, and if those objects are not in collision at this physics step, returns nil; if they are in collision, returns a pair of two objects like those passed, except that each has a 3d vector object added to its `:deltas` property.
|
||||
|
||||
Thus, `(pmap collide (combinations objects 2))` will return a flat list with potentially many copies of the same object, each with different deltas; but it will not contain any copies of any objects which weren't in collision at all.
|
||||
|
||||
Consequently, `merge-collisions` must, for every key in the objects, collect each of the copies of that object from the collisions and from the original objects list, and, for each key, return one object identical to the original object except that its `:deltas` property is a concatentation of the `:deltas` properties of each of the copies:
|
||||
|
||||
```clojure
|
||||
(defn merge-collisions
|
||||
[collision-pairs objects]
|
||||
(pmap
|
||||
#(assoc (first %) :deltas (apply concat (map :deltas %)))
|
||||
(partition-by :id
|
||||
(sort-by :id
|
||||
(concat
|
||||
(flatten collision-pairs)
|
||||
objects)))))
|
||||
```
|
||||
|
||||
`apply-gravity` is simply a function which returns an object like the object passed to it, but with a constant acceleration-under-gravity vector added to its `:deltas` property;
|
||||
|
||||
`apply-friction` is a fairly simple function which computes a friction vector in the direction opposite to the current velocity object passed to it, and returns an object like the object passed but with that fricton vector added to its `:deltas` property;
|
||||
|
||||
and finally,
|
||||
|
||||
`merge-vectors` is a function which takes an object with a `:position`, a `:velocity`, and a (possibly empty) sequence of `:deltas`, computes a new `:velocity` vector produced by applying each of the deltas in turn to the velocity, and a new `:position` produced by adding that new `:velocity` (times the duration of the tick) to the old position. It returns an object like the object passed but with the new `:position` and `:velocity` values. I'm too tired to confidently state the maths of that now, but I'm confident it's simple.
|
||||
|
||||
Which means, in fact, that the whole thing is simple (modulo the `collide` function, which I haven't even sketched above, and which is somewhat dependent on the models involved).
|
||||
|
||||
Note that, however
|
||||
|
||||
1. At this stage it considers only velocity deltas, not spin deltas; it ought to do that too, but, although that adds extra operations, it doesn't add complexity; and
|
||||
2. This currently considers only rigid bodies. Soft bodies are a significantly more complex problem.
|
|
@ -1,4 +1,4 @@
|
|||
# Game world economy
|
||||
# Game world economy (unfinished)
|
||||
|
||||
Broadly this essay extends ideas presented in [Populating a game world](Populating-a-game-world.html), q.v.
|
||||
|
||||
|
|
|
@ -4,8 +4,19 @@ Work by other people which is relevant to what I'm doing, and which I should stu
|
|||
|
||||
## Modelling the natural environment
|
||||
|
||||
### Forests
|
||||
|
||||
1. [Synthetic Silviculture: Multi-scale Modeling of Plant Ecosystems](https://storage.googleapis.com/pirk.io/projects/synthetic_silviculture/index.html) — see also [this video](https://youtu.be/8YOpFsZsR9w).
|
||||
|
||||
### Water
|
||||
|
||||
1. [Effective Water Simulation from Physical Models](https://developer.nvidia.com/gpugems/gpugems/part-i-natural-effects/chapter-1-effective-water-simulation-physical-models)
|
||||
2. [Modelling Ocean Water](https://people.computing.clemson.edu/~jtessen/reports/papers_files/coursenotes2004.pdf)
|
||||
|
||||
## Systemic games
|
||||
|
||||
1. [This video](https://youtu.be/SnpAAX9CkIc) is thought provoking with excellent examples.
|
||||
|
||||
## Procedural animation
|
||||
|
||||
1. [This video](https://youtu.be/LNidsMesxSE) builds really impressive character animation on extremely simple foundations. I'm not saying this is easy, but it looks doable.
|
|
@ -1,4 +1,4 @@
|
|||
# Game Play
|
||||
# Game Play (unfinished)
|
||||
|
||||
The principles of game play which I'm looking for are a reaction against all I see as wrong in modern video games. So let's set out what these are:
|
||||
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
# The Red Company: modelling democracy and morale (unfinished)
|
||||
|
||||
## Background
|
||||
|
||||
The Great Game exists as a project on two levels. One one level, it's a framework for building algorithms to build much more vibrant, and thus enjoyable game worlds; at another level, it's about building a particular world, in which I want to tell stories.
|
||||
|
||||
The world in which I want to tell stories is a world which is based roughly on late bronze age to medieval Europe. It's a world in which the region known as 'The Coast' — the southern littoral of the continent — had been a mostly-peaceful matrideic dispersed agrarian tribal society, which had been invaded some hundreds of years past by a warrior tribe with substantially better military technology.
|
||||
|
||||
These warrior tribesmen have settled down as local tyrants or robber barons, parasitising on the indigenous communities, and have evolved into an aristocratic ('Ariston') class. In the meantime, a mercantile class has grown up and established important long distance overland trade routes; and significant towns (called 'cities', but of only at most a few tens of thousand inhabitants) have grown up around markets.
|
||||
|
||||
These mercantile cities have been under the governance of powerful aristons known as tyrranoi, and the cities under their tyrranoi have competed militarily as well as commercially for control of strategic features on trade routes, such as bridges, fords, oases, mountain passes, and so on.
|
||||
|
||||
In the very earliest days of the warrior invasion, the warriors themselves fought against the indigenous peoples, who had very limited military equipment and tactics. Later, as they settled into Aristons, they fought by leading feudal levies of partially-trained peasants. Over the past hundred years or so, mercenary companies have emerged of specialist, trained warriors, and because these have more fighting experience (and often better equipment) they tend to beat feudal levies. These mercenary companies are base loosely on the condottierri of fourteenth century Italy.
|
||||
|
||||
So more and more, tyrranoi, rather than leading their own feudal levies, instead tax their peasantry and mercantile class more and hire condottierri to fight their wars.
|
||||
|
||||
Mercenary companies evolve out of feudal levies, and in the period of The Great Game, are mostly owned and led by aristons who employ their soldiers by paying them a wage.
|
||||
|
||||
One company, the Red Company, has become essentially a workers' co-op, after its former ariston leader fled in the course of a battle which looked like an inevitable defeat (but which the company, without him, won). In this company, soldiers are paid a salary, probably lower than salaries in other companies, but also at the end of the year get a share in the profits. The soldiers are organised into squads of eight who elect their own sergeants; squads are organised into companies of eight squads, and the sergeants elect the captain; companies are organised into legions of eight companies, and the captains elect the captain-general.
|
||||
|
||||
However, while in combat this represents a chain of command, out of combat it is much more a delegate structure; when making significant decisions, the captains general will consult with the captains who will consult with the sergeants who will consult with the soldiers.
|
||||
|
||||
One of the themes of the stories I want to tell is that this more democratic structure contributes to higher morale and hence to greater military success. I could model this by just making membership of the Red Company a factor in the function which computes morale. However...
|
||||
|
||||
## Modelling democracy
|
||||
|
||||
If each individual character has a hierarchy of needs, and plans actions based on that hierarchy of needs, then they have the mechanism in place to choose which of two options better conforms to their hierarchy of needs.
|
||||
|
||||
This implies that soldiers are likely to vote for the people (or ideas presented by the people) they consider most competent and/or most trustworthy. Which comes back to modelling reputation; which comes back to the [gossip](the-great-game.gossip.gossip.html).
|
|
@ -1,5 +1,7 @@
|
|||
# Naming of Characters
|
||||
|
||||
**See [`wherefore-art-thou`](https://github.com/simon-brooke/wherefore-art-thou)**
|
||||
|
||||
Generally speaking, in modern RPGs, every character with any impact on the plot has a distinct name. But if we are going to give all non-player characters sufficient agency to impact on the plot, then we must have a way of naming tens or hundreds of thousands of characters, and distinct names will become problematic (even if we're procedurally generating names, which we shall have to do. So this note is about how characters are named.
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Not my problem
|
||||
# Not my problem
|
||||
|
||||
## Introduction
|
||||
|
||||
|
|
76
doc/Towards-a-procedural-animation-api.md
Normal file
76
doc/Towards-a-procedural-animation-api.md
Normal file
|
@ -0,0 +1,76 @@
|
|||
# Towards a procedural animation API
|
||||
|
||||
I've been watching this animation tutorial, and I'm impressed with its simplicity. This seems to be to be something it would be possible to do, and it started me thinking about what I wanted from a procedural animation API.
|
||||
|
||||
<iframe width="800" height="504" src="https://www.youtube.com/embed/LNidsMesxSE?si=QgaN2aHG0g71aWkX" title="An Indie Approach to Procedural Animation" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
|
||||
|
||||
The game is now open source, with the source available [here](https://github.com/WolfireGames/overgrowth/). It's available on [Steam, here](https://store.steampowered.com/app/25000/Overgrowth/).
|
||||
|
||||
So: what have we here?
|
||||
|
||||
A simple character rig with a small number of key frames which can adaptively negotiate a moderately complex terrain. Inverse kinematics is used, but the core of the animation is key-frame animation with well thought out interpolation, and it all looks remarkably persuasive. This looks buildable.
|
||||
|
||||
So: what do I actually need?
|
||||
|
||||
## Smooth continuous movement on complex terrain
|
||||
|
||||
Characters need to transition from one movement to another movement smoothly, without sudden jums or jerks. Turning needs to look physically plausible.
|
||||
|
||||
## Animation for several skeleton types
|
||||
|
||||
Creatures I need to animate include
|
||||
|
||||
1. People: upright bipedal motion;
|
||||
2. Horses: even-length-legged quadripedal motion;
|
||||
3. Camels: also even length legged quadripeds, but their gait is different from horses, although the skeleton might be similar. So: different key frames? Or something more elaborate than that?
|
||||
4. Seals: primarily aquatic quadrupeds, with forelimbs considerably longer than back limbs, and all limbs much shorter than the other quadripeds under consideration. But I'm not sure how much I need to actually animate them.
|
||||
5. Dragons: exist in the world, but aren't necessarily going to appear in version one of the game. A much more complicated problem.
|
||||
6. Birds: but don't need to animate them close up or landed. However, not all birds fly using the same 'gait', so, again this may be complex.
|
||||
7. Other quadrupeds, such as dogs and cats; but these are a long way down the priority scale.
|
||||
|
||||
At the proof of concept stage, I only need animated people; and the only reason for cataloguing the other things I need to animate is that the animation framework needs to be able to handle multiple skeleton types.
|
||||
|
||||
It's also worth pointing out that in Cyberpunk 2077, it's very noticable that several different gaits are implemented for people: there is a noticably distinct 'fat person' gait, and several different gaits that are used, for example one extremely sexualised female gait, used mainly for characters who are sex workers, but for a small number of other female characters. The point here is that not all characters walk the same, and having distinctive gaits for some characters or classes of characters decidedly adds to a game's persuasiveness.
|
||||
|
||||
## The API
|
||||
|
||||
### (move-to model terrain target)
|
||||
|
||||
Plans a route across the terrain from where the model is to the target (which can be either a location or an object, including another potentially moving character), avoiding obstacles and choosing the easiest path across slopes, and produces a route; animates the model along that route, using the keyframe-based system described in the video, with inverse kinematics to ensure feet touch the ground.
|
||||
|
||||
### (look-at model terrain target)
|
||||
|
||||
Turns the model's gaze, and, if necessary, head and body, to face towards the target.
|
||||
|
||||
### (sit-on model terrain target)
|
||||
|
||||
Causes the model to sit on the target, moving to it first if necessary. If the target is approximately chair-height, sit on it as if on a chair; if it's a horse or camel, sit on it as though to ride; otherwise, sit cross legged. If the target is just a location, sit cross legged on the terrain surface at that location.
|
||||
|
||||
Obviously, what I've described there is partially specific to upright bipedal models; horses and camels don't sit on chairs!
|
||||
|
||||
### (lie-on model terrain target)
|
||||
|
||||
As above, but lie down.
|
||||
|
||||
### (drink-from model terrain target)
|
||||
|
||||
As above, but drink. Target is expected to be a drinkable container, such as a mug, flask or bottle, or else a point in the terrain which is flooded.
|
||||
|
||||
### (eat-from model terrain target)
|
||||
|
||||
### (strike model terrain target implement vector)
|
||||
### (thrust model terrain target implement vector)
|
||||
|
||||
Two closely related animation calls, both of which might be used both in combat animation and in craft activity animation. **BUT** both combat animation and craft activity animation are much more complex problems which this not does not address.
|
||||
|
||||
## Other things which need to be animated
|
||||
|
||||
### Conversation
|
||||
|
||||
In conversation, people move to a convenient distance from one another, typically face one another, typically take turns to say things, frequently use hand gestures when speaking. The intensity of gestures will vary with the emotion being expressed. The animation of NPC-to-NPC conversation is if possible more complex to get right than of player character to NPC.
|
||||
|
||||
### Combat animation
|
||||
|
||||
### Craft activity animation
|
||||
|
||||
Both of these will be very complicated to get right.
|
16
doc/Useful-software-libraries.md
Normal file
16
doc/Useful-software-libraries.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Useful software tools and libraries (open source)
|
||||
|
||||
## Animation
|
||||
|
||||
* [Papagayo](https://www.lostmarble.com/papagayo/) -- lipsync animator, not up to JALI standards, but not nothing! However, not apparently under active development, and in C++.
|
||||
|
||||
## Procedural assets
|
||||
|
||||
## Textures
|
||||
|
||||
* [Poly Haven](https://polyhaven.com/) -- free textures, also HDRI lighting maps and some 3D models, although few look relevant.
|
||||
|
||||
## Others
|
||||
|
||||
* [Festival Speech Synthesis](https://www.cstr.ed.ac.uk/projects/festival/download.html) Text to speech library, in C++ but there's a Java transducer.
|
||||
* [Mary TTS](https://github.com/marytts/marytts) Text to speech library, probably not as good as Festival
|
134
docs/codox/3D-formats.html
Normal file
134
docs/codox/3D-formats.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
33
docs/codox/Architecture.html
Normal file
33
docs/codox/Architecture.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
61
docs/codox/Draft-algorithm-functional-physics-engine.html
Normal file
61
docs/codox/Draft-algorithm-functional-physics-engine.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
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
6
docs/codox/Pseudo-object-inheritance.html
Normal file
6
docs/codox/Pseudo-object-inheritance.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
47
docs/codox/Towards-a-procedural-animation-api.html
Normal file
47
docs/codox/Towards-a-procedural-animation-api.html
Normal file
File diff suppressed because one or more lines are too long
52
docs/codox/Tree-library-evaluation.html
Normal file
52
docs/codox/Tree-library-evaluation.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
18
docs/codox/Useful-software-libraries.html
Normal file
18
docs/codox/Useful-software-libraries.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
24
docs/codox/cc.journeyman.the-great-game.agent.agent.html
Normal file
24
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
8
docs/codox/cc.journeyman.the-great-game.launcher.html
Normal file
8
docs/codox/cc.journeyman.the-great-game.launcher.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
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
10
project.clj
10
project.clj
|
@ -1,4 +1,4 @@
|
|||
(defproject journeyman-cc/the-great-game "0.1.3-SNAPSHOT"
|
||||
(defproject journeyman-cc/the-great-game "0.1.3"
|
||||
:cloverage {:output "docs/cloverage"
|
||||
:codecov? true
|
||||
:emma-xml? true}
|
||||
|
@ -11,14 +11,14 @@
|
|||
: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 [
|
||||
;; sadly it seems SQL Korma is dead. I'm experimenting with Honey SQL,
|
||||
:dependencies [;; sadly it seems SQL Korma is dead. I'm experimenting with Honey SQL,
|
||||
;; but this is not a final decision yet.
|
||||
[com.github.seancorfield/honeysql "2.6.1126"]
|
||||
[com.github.seancorfield/next.jdbc "1.3.925"]
|
||||
[com.simsilica/lemur "1.16.1-SNAPSHOT"]
|
||||
[com.simsilica/lemur "1.16.0"]
|
||||
[com.simsilica/sim-arboreal "1.0.1-SNAPSHOT"]
|
||||
[com.taoensso/timbre "6.5.0"]
|
||||
;; [com.taoensso/timbre "6.5.0"]
|
||||
[com.taoensso/telemere "1.0.0-beta3"] ;; Peter Taoussanis' new replacement for Timbre
|
||||
[environ "1.2.0"]
|
||||
[hiccup "2.0.0-RC3"]
|
||||
[jme-clj "0.1.13"]
|
||||
|
|
|
@ -4,6 +4,32 @@
|
|||
(:require [cc.journeyman.the-great-game.objects.game-object :refer [ProtoObject]]
|
||||
[cc.journeyman.the-great-game.objects.container :refer [ProtoContainer contents is-empty?]]))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;
|
||||
;;;; Agents: things with agency.
|
||||
;;;;
|
||||
;;;; This program is free software; you can redistribute it and/or
|
||||
;;;; modify it under the terms of the GNU General Public License
|
||||
;;;; as published by the Free Software Foundation; either version 2
|
||||
;;;; of the License, or (at your option) any later version.
|
||||
;;;;
|
||||
;;;; This program is distributed in the hope that it will be useful,
|
||||
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;;; GNU General Public License for more details.
|
||||
;;;;
|
||||
;;;; You should have received a copy of the GNU General Public License
|
||||
;;;; along with this program; if not, write to the Free Software
|
||||
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
;;;; USA.
|
||||
;;;;
|
||||
;;;; SPDX-FileCopyrightText: 2024 Simon Brooke <simon@journeyman.cc>
|
||||
;;;; SPDX-License-Identifier: GPL-2.0-or-later
|
||||
;;;;
|
||||
;;;; Copyright (C) 2024 Simon Brooke
|
||||
;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;;; 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.
|
||||
|
|
|
@ -2,6 +2,33 @@
|
|||
"Schedules of plans for actors in the game, in order that they may have
|
||||
daily and seasonal patterns of behaviour.")
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;
|
||||
;;;; Schedules: things agents plan to do.
|
||||
;;;;
|
||||
;;;; This program is free software; you can redistribute it and/or
|
||||
;;;; modify it under the terms of the GNU General Public License
|
||||
;;;; as published by the Free Software Foundation; either version 2
|
||||
;;;; of the License, or (at your option) any later version.
|
||||
;;;;
|
||||
;;;; This program is distributed in the hope that it will be useful,
|
||||
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
;;;; GNU General Public License for more details.
|
||||
;;;;
|
||||
;;;; You should have received a copy of the GNU General Public License
|
||||
;;;; along with this program; if not, write to the Free Software
|
||||
;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
;;;; USA.
|
||||
;;;;
|
||||
;;;; SPDX-FileCopyrightText: 2024 Simon Brooke <simon@journeyman.cc>
|
||||
;;;; SPDX-License-Identifier: GPL-2.0-or-later
|
||||
;;;;
|
||||
;;;; Copyright (C) 2024 Simon Brooke
|
||||
;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
|
||||
;; TODO: I don't have a good handle yet on when a new scheduled task can
|
||||
;; interrupt an existing scheduled task. It's highly undesirable that
|
||||
;; uncompleted scheduled tasks should be left on the queue. The simplest
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
to mean a special character who is part of the news-passing network."
|
||||
(:require [cc.journeyman.the-great-game.gossip.gossip :refer [dialogue]]
|
||||
[cc.journeyman.the-great-game.agent.agent :refer [ProtoAgent]]
|
||||
[cc.journeyman.the-great-game.character.container :refer [ProtoContainer]]
|
||||
[cc.journeyman.the-great-game.objects.container :refer [ProtoContainer]]
|
||||
[clojure.string :as cs :only [join]])
|
||||
(:import [clojure.lang IPersistentMap]))
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
[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]))
|
||||
[taoensso.telemere.timbre :as l]))
|
||||
|
||||
(declare interesting-location?)
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
(declare game)
|
||||
|
||||
(def cli-options
|
||||
"I haven't yet thought out what command line arguments (if any) I need.
|
||||
This is a placeholder."
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
(ns cc.journeyman.the-great-game.merchants.markets
|
||||
"Adjusting quantities and prices in markets."
|
||||
(:require [taoensso.timbre :as l :refer [info error]]
|
||||
(:require [taoensso.telemere.timbre :as l :refer [info error]]
|
||||
[cc.journeyman.the-great-game.utils :refer [deep-merge]]))
|
||||
|
||||
(defn new-price
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"Trade planning for merchants, primarily."
|
||||
(: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]))
|
||||
[taoensso.telemere.timbre :as l]))
|
||||
|
||||
|
||||
(defn run
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
and sells it there. If there is no commodity locally which can be traded
|
||||
profitably, moves towards home with no cargo. If at home and no commodity
|
||||
can be traded profitably, does not move."
|
||||
(:require [taoensso.timbre :as l :refer [info error spy]]
|
||||
(:require [taoensso.telemere.timbre :as l :refer [info error]]
|
||||
[cc.journeyman.the-great-game.utils :refer [deep-merge]]
|
||||
[cc.journeyman.the-great-game.gossip.gossip :refer [move-gossip]]
|
||||
[cc.journeyman.the-great-game.merchants.planning :refer [augment-plan plan-trade select-cargo]]
|
||||
|
@ -72,7 +72,6 @@
|
|||
(map? merchant)
|
||||
merchant)
|
||||
id (:id m)
|
||||
location (:location m)
|
||||
plan (augment-plan m world (plan-trade m world (-> m :plan :commodity)))]
|
||||
(l/debug "re-plan: merchant" id)
|
||||
(deep-merge
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
[mw-engine.heightmap :refer [apply-heightmap]]
|
||||
[mw-engine.utils :refer [map-world]]
|
||||
[mw-parser.declarative :refer [compile]]
|
||||
[taoensso.timbre :refer [info]]
|
||||
[taoensso.telemere.timbre :refer [info]]
|
||||
[wherefore-art-thou.core :refer [*genders* generate]]))
|
||||
|
||||
(defn get-drainage-map
|
||||
|
@ -45,8 +45,8 @@
|
|||
;; persist them in the database being built. This is just a sketch.
|
||||
[prototype]
|
||||
(let [g (or (:gender prototype) (rand-nth (keys *genders*)))
|
||||
p (generate g)]
|
||||
(dissoc (merge {:age (+ 18 (rand-int 18))
|
||||
p (generate g)
|
||||
npc (dissoc (merge {:age (+ 18 (rand-int 18))
|
||||
:disposition (- (rand-int 9) 4) ;; -4: surly to +4 sunny
|
||||
:gender g
|
||||
:goal (rand-nth *life-goals*)
|
||||
|
@ -55,7 +55,9 @@
|
|||
:personal-name p} prototype)
|
||||
;; it's useful to have the world available to the create function,
|
||||
;; but we don't want to return it in the results because clutter.
|
||||
:world)))
|
||||
:world)]
|
||||
(info (format "Created NPC %s" (select-keys npc [:id :family-name :personal-name :age :gender :occupation :goal])))
|
||||
))
|
||||
|
||||
(defn- populate-npcs
|
||||
[prototype]
|
||||
|
@ -65,7 +67,7 @@
|
|||
|
||||
(defn populate-cell
|
||||
[world cell]
|
||||
;; (info (format "populate-cell: w is %s; cell is %s" (type world) cell))
|
||||
(info (format "populate-cell: w is %s; cell is %s" (type world) cell))
|
||||
(let [npcs (case (:state cell)
|
||||
:camp (populate-npcs {:world world :cell cell :occupation :nomad})
|
||||
:house (populate-npcs {:world world :cell cell :occupation :peasant})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
(ns cc.journeyman.the-great-game.world.run
|
||||
"Run the whole simulation"
|
||||
(:require [environ.core :refer [env]]
|
||||
[taoensso.timbre :as timbre]
|
||||
[taoensso.telemere.timbre :as timbre]
|
||||
[taoensso.timbre.appenders.3rd-party.rotor :as rotor]
|
||||
[cc.journeyman.the-great-game.gossip.gossip :as g]
|
||||
[cc.journeyman.the-great-game.merchants.merchants :as m]
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue